Static Contract Checking for Haskell

Similar documents
Extended Static Checking for Haskell (ESC/Haskell)

From Types to Contracts

Static Contract Checking for Haskell

Extended Static Checking for Haskell

Functional Programming and Haskell

PROGRAMMING IN HASKELL. CS Chapter 6 - Recursive Functions

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Haskell Functions

Combining Static and Dynamic Contract Checking for Curry

Shell CSCE 314 TAMU. Functions continued

CS 360: Programming Languages Lecture 10: Introduction to Haskell

Programming Languages Fall 2013

Practical Haskell. An introduction to functional programming. July 21, Practical Haskell. Juan Pedro Villa-Isaza. Introduction.

Lambda Calculus: Implementation Techniques and a Proof. COS 441 Slides 15

It is better to have 100 functions operate one one data structure, than 10 functions on 10 data structures. A. Perlis

More Untyped Lambda Calculus & Simply Typed Lambda Calculus

Optimising Functional Programming Languages. Max Bolingbroke, Cambridge University CPRG Lectures 2010

Programming Languages Fall 2013

CS 11 Haskell track: lecture 1

Fall 2013 Midterm Exam 10/22/13. This is a closed-book, closed-notes exam. Problem Points Score. Various definitions are provided in the exam.

Testing. Wouter Swierstra and Alejandro Serrano. Advanced functional programming - Lecture 2. [Faculty of Science Information and Computing Sciences]

CSC312 Principles of Programming Languages : Functional Programming Language. Copyright 2006 The McGraw-Hill Companies, Inc.

CPM: A Declarative Package Manager with Semantic Versioning

Reasoning About Imperative Programs. COS 441 Slides 10

Haskell 101. (Version 1 (July 18, 2012)) Juan Pedro Villa Isaza

CS 360: Programming Languages Lecture 12: More Haskell

Haskell Introduction Lists Other Structures Data Structures. Haskell Introduction. Mark Snyder

Functional Programming in Haskell Part I : Basics

Functional Programming

Formal Systems and their Applications

CSc 372. Comparative Programming Languages. 8 : Haskell Function Examples. Department of Computer Science University of Arizona

Simon Peyton Jones (Microsoft Research) Max Bolingbroke (University of Cambridge)

Lecture 6: Sequential Sorting

QuickCheck, SmallCheck & Reach: Automated Testing in Haskell. Tom Shackell

Programming Languages 3. Definition and Proof by Induction

Advanced Type System Features Tom Schrijvers. Leuven Haskell User Group

GADTs. Wouter Swierstra. Advanced functional programming - Lecture 7. Faculty of Science Information and Computing Sciences

Functional Logic Programming Language Curry

Introduction to Haskell

CS131 Typed Lambda Calculus Worksheet Due Thursday, April 19th

Advanced features of Functional Programming (Haskell)

Introduction to Programming: Lecture 6

Informatics 1 Functional Programming Lecture 11. Data Representation. Don Sannella University of Edinburgh

Programming Languages Fall 2014

Type families and data kinds

Denotational Semantics. Domain Theory

A general introduction to Functional Programming using Haskell

Shell CSCE 314 TAMU. Haskell Functions

CIS 500 Software Foundations Midterm I

Haskell: From Basic to Advanced. Part 2 Type Classes, Laziness, IO, Modules

Simon Peyton Jones Microsoft Research August 2013

Lambda Calculus. Concepts in Programming Languages Recitation 6:

Functional Programming. Overview. Topics. Definition n-th Fibonacci Number. Graph

CITS3211 FUNCTIONAL PROGRAMMING. 7. Lazy evaluation and infinite lists

CSc 372 Comparative Programming Languages

GADTs. Wouter Swierstra and Alejandro Serrano. Advanced functional programming - Lecture 7. [Faculty of Science Information and Computing Sciences]

Functional Programming for Logicians - Lecture 1

Programming Languages Lecture 14: Sum, Product, Recursive Types

Modules and Representation Invariants

Once Upon a Polymorphic Type

GADTs. Alejandro Serrano. AFP Summer School. [Faculty of Science Information and Computing Sciences]

FUNCTIONAL PEARLS The countdown problem

Formal Semantics. Prof. Clarkson Fall Today s music: Down to Earth by Peter Gabriel from the WALL-E soundtrack

Informatics 1 Functional Programming Lecture 12. Data Abstraction. Don Sannella University of Edinburgh

Haske k ll An introduction to Functional functional programming using Haskell Purely Lazy Example: QuickSort in Java Example: QuickSort in Haskell

Advanced Topics in Programming Languages Lecture 2 - Introduction to Haskell

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

Theorem Proving Principles, Techniques, Applications Recursion

CS 320: Concepts of Programming Languages

MPRI course 2-4 Functional programming languages Exercises

Logic - CM0845 Introduction to Haskell

This example highlights the difference between imperative and functional programming. The imperative programming solution is based on an accumulator

Simon Peyton Jones Microsoft Research August 2012

Haskell through HUGS THE BASICS

An introduction introduction to functional functional programming programming using usin Haskell

Exercise 1 ( = 22 points)

Haskell Overview II (2A) Young Won Lim 8/9/16

Solution sheet 1. Introduction. Exercise 1 - Types of values. Exercise 2 - Constructors

Topic 7: Algebraic Data Types

CSci 4223 Principles of Programming Languages

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

CS 457/557: Functional Languages

What does my program mean?

List Functions, and Higher-Order Functions

Arbitrary-rank polymorphism in (GHC) Haskell

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

4. Logical Values. Our Goal. Boolean Values in Mathematics. The Type bool in C++

Haskell 5.1 INTERACTIVE SESSIONS AND THE RUN-TIME SYSTEM

A CRASH COURSE IN SEMANTICS

PROGRAMMING IN HASKELL. Chapter 5 - List Comprehensions

Haskell Syntax in Functions

Finding the Needle Stack Traces for GHC

Rethinking Automated Theorem Provers?

Lambda Calculus and Type Inference

Programming Languages Third Edition

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Winter 2013

Exercise 1 ( = 24 points)

λ calculus Function application Untyped λ-calculus - Basic Idea Terms, Variables, Syntax β reduction Advanced Formal Methods

COMP80 Lambda Calculus Programming Languages Slides Courtesy of Prof. Sam Guyer Tufts University Computer Science History Big ideas Examples:

An introduction to functional programming. July 23, 2010

Simon Peyton Jones Microsoft Research. August 2012

Transcription:

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

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

From Types to Contracts head (x:xs) = x head :: [Int] -> Int Type not :: Bool -> Bool not True = False not False = True (head 1) Bug! null :: [a] -> Bool null [] = True null (x:xs) = False head 2 {xs not (null xs)} -> {r True} (head []) Bug! Contract (original Haskell boolean expression) 3

What we want? Contract Haskell Program Glasgow Haskell Compiler (GHC) Where the bug is Why it is a bug 4

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! 5

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

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 7

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. 8

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 9

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] 10

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 True} -> {r (n<=100 && r==91) r==n-10} f91 n = case (n <= 100) of True -> f91 (f91 (n + 11)) False -> n 10 11

Sorting (==>) True x = x (==>) False x = True 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} 12

AVL Tree (&&) True x = x (&&) False x = False 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}

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! 14

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... 15

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 16

Two Exceptional Values BAD is an expression that crashes. error :: String -> a error s = BAD head (x:xs) = x head [] = BAD div x y = case y == 0 of True -> error divide by zero False -> x / y head (x:xs) = x Real Haskell Program 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) 17

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

What is a Contract (related to [Findler:ICFP02,Blume:ICFP04,Hinze:FLOPS06,Flanagan:POPL06]) 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 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} 20

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}? 21

What exactly does it mean to say that e satisfies contract t? e 2 t 22

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

Only Crash-free Expression Satisfies a Predicate Contract e 2 {x p}, e" or (e is crash-free and p[e/x]! * {BAD, False} e2 x:t 1! t 2, e" or (e! * x.e and 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

All Expressions Satisfy Any fst 2 ({x True}, Any) -> {r True} fst (a,b) = a g x = fst (x, BAD) Inlining may help, but breaks down when function definition is big or recursive 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 25

All Contracts are Inhabited e 2 {x p}, e" or (e is crash-free and p[e/x]! * {BAD, False} e2 x:t 1! t 2, e" or (e! * x.e and 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

What to Check? Does function f satisfy its contract t (written f2 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) 27

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

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

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 (vc t 1 )) B t 2 [vct 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] 30

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] 31

Example head:: [a] -> a head [] = BAD head (x:xs) = x head { xs not (null xs) } -> Ok head {xs not (null xs)} -> Ok = \v. head (v {xs not (null xs)}) Ok e Ok = e = \v. head (v {xs not (null xs)}) = \v. head (case not (null v) of True -> v False -> UNR)

\v. head (case not (null v) of True -> v False -> UNR) Now inline not and null = \v. head (case v of [] -> UNR (p:ps) -> p) Now inline head = \v. case v of [] -> UNR (p:ps) -> p null :: [a] -> Bool null [] = True null (x:xs) = False not :: Bool -> Bool not True = False not False = True So head [] fails with UNR, not BAD, blaming the caller

Higher-Order Function 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) 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

Grand Theorem e 2 t, e B t is crash-free 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 e_1 `seq` e_2 = case e_1 of {DEFAULT -> e_2} 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

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 crash-free e B {x p} = e `seq` case fin p[e/x] of True -> e False -> BAD fin converts divergence to True

Contracts that Crash Grand Theorem e 2 t, e B t is crash-free 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

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 8e 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

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 40

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 ec t Lemma [A Projection Pair]: 8 e, t. e B t C t ¹ e Lemma [A Closure Pair]: 8 e, t. e ¹ ec t B t 41

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

Simplification Rules 43

Arithmetic via External Theorem Prover goo B t goo = \i -> case (i+8 > i) of False -> BAD foo True -> >>ThmProver i+8>i >>Valid! >>ThmProver push(i>j) push(not (j<0)) (i>0) case i > j of >>Valid! True -> case j < 0 of False -> case i > 0 of False -> BAD f

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 45

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 46

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 47

Counter-Example Guided Unrolling The Algorithm 48

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 Inside g lc (g C t g ) case fin p[e/x] of True -> e False -> BAD f (\g! g ) B t g! t f 49

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

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

Summary Static contract checking is a fertile and under-researched area Distinctive features of our approach Full Haskell in contracts; absolutely crucial Declarative specification of satisfies Nice theory (with some very tricky corners) Static proofs Modular Checking Compiler as theorem prover

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

Recursion f Bt =\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 Bt1)) C t2)) (v2c t1) ) B t2) 54