Logic
Prof. Dr. K. Madlener
13. April 2011
Chapter 1
Functional Programming:
Reminder
Functional Programming
Fact1.1. A functional program consists of
I data type declarations
I function declarations
I an expression
Functional Programs
I do not have variables, assigments, statements, loops, ...
I instead:
I let-expressions
I recursive functions
I higher-order functions
Functional Programming
Advantages
I clearer semantics
I corresponds more directly to abstract mathematical objects
I more freedom in implementation
The SML Programming Language
Overview
I functional programming language
I interpreter and compiler available
I strongly typed, with:
I type inference
I abstract data types
I parametric polymorphism
I exception-handling mechanisms
Motivation
I ML is similar to functional core of Isabelle/HOL specification language
I ML is the implementation language of the theorem prover
Evaluation and Bindings
Example1.2. Evaluation - 2 + 3;
val it = 5 : int
- rev [1 ,2 ,3 ,4 ,5];
val it = [5 ,4 ,3 ,2 ,1] : int l i s t Example1.3. Simple Bindings
- val n = 8 * 2 + 5;
val n = 21 : int
- n * 2;
Bindings
Example1.4. Special Identifierit - it;
val it = 42 : int
Example1.5. Multiple Bindings
- val one = 1 and two = 2;
val one = 1 : int val two = 2 : int
Local Bindings
Example1.6. Simple Local Binding
- val n = 0;
val n = 0 : int
- let val n = 12 in n div 6 end;
val it = 2 : int
- n;
val it = 0 : int
Example1.7. Multiple Local Bindings
- let val n = 5 val m = 6 in n + m end;
Booleans
Example1.8. Operations
- val b1 = t r u e and b2 = f a l s e; val b1 = t ru e : b o o l
val b2 = f a l s e : b o o l - 1 = (1 + 1) ;
val it = f a l s e : b o o l - not (b1 o r e l s e b2) ; val it = f a l s e : b o o l
- (7 < 3) a n d a l s o (f a l s e o r e l s e 2 > 0) ; val it = f a l s e : b o o l
Integers
Example1.9. Operations - val n = 2 + (3 * 4) ;
val n = 14 : int
- val n = (10 div 2) - 7;
val n = ~2 : int
Applying Functions
General Rules
I type of functions fromσ1toσ2isσ1→σ2
I applicationf x applies functionf to argumentx
I call-by-value (obvious!)
I left associative:m n o p= (((m n)o)p)
Defining Functions
Example1.10. One Argument
- fun f n = n + 2;
val f = fn : int - > int - f 22;
val it = 24 : int
Example1.11. Two or More Arguments - fun p l u s n (m:int) = n + m;
val p l u s = fn : int - > int - > int - p l u s 2 3;
Currying
Example1.12. Curried Addition - fun p l u s n (m:int) = n + m;
val p l u s = fn : int - > int - > int - p l u s 1 2;
val it = 3 : int
Example1.13. Partial Application - val inc = p l u s 1;
val inc = fn : int - > int - inc 7;
val it = 8 : int
Higher-Order Functions
Example1.14. Higher-Order Functions - fun foo f n = (f(n+1) ) div 2 ;
val foo = fn : (int - > int) - > int - > int
- foo inc 3;
val it = 2 : int
Recursive Functions
Example1.15. Defining Recursive Functions
- fun f n = if (n=0) t h e n 1 e l s e n * f(n-1) ; val f = fn : int - > int
- f 3;
val it = 6 : int
- fun m e m b e r x [] = f a l s e |
m e m b e r x (h: :t) = (x=h) o r e l s e (m e m b e r x t) ; val m e m b e r = fn : ’ ’a - > ’ ’a l i s t - > b o o l
- m e m b e r 3 [1 ,2 ,3 ,4];
val it = t ru e : b o o l
Lambda Abstractions
Example1.16. The Increment Function - fn x= > x + 1;
val it = fn : int - > int - (fn x= > x + 1) 2;
val it = 3 : int
Lambda Abstractions
Example1.17. Curried Multiplication - fn x= > fn y= > x * (y:int) ; val it = fn : int - > int - > int
- val d o u b l e = (fn x= > fn y= > x * (y:int) ) 2;
val d o u b l e = fn : int - > int - d o u b l e 22;
val it = 44 : int
Clausal Definitions
Example1.18. Fibonacci fun fib 0 = 1
| fib 1 = 1
| fib n = fib(n-1) + fib(n-2) ;
Exceptions
Example1.19. Failure - hd [];
u n c a u g h t e x c e p t i o n Hd - 1 div 0;
u n c a u g h t e x c e p t i o n Div
User-Defined Exceptions
Example1.20. Explicitly Generating Failure - e x c e p t i o n n e g a t i v e _ a r g u m e n t _ t o _ f a c t; e x c e p t i o n n e g a t i v e _ a r g u m e n t _ t o _ f a c t - fun f a c t n =
if (n<0) t h e n r a i s e n e g a t i v e _ a r g u m e n t _ t o _ f a c t e l s e if (n=0) t h e n 1 el s e n * f a c t(n-1) ; val f a c t = fn : int - > int
- f a c t (~1) ;
u n c a u g h t e x c e p t i o n n e g a t i v e _ a r g u m e n t _ t o _ f a c t Example1.21. Exception Handling
Unit
Example1.22. Unit - () ;
val it = () : u n i t - c l o s e _ t h e o r y;
val it = fn : u n i t - > un i t
Character Strings
Example1.23. String Operations - " abc ";
val it = " abc " : s t r i n g - chr;
val it = fn : int - > s t r i n g - chr 97;
val it = " a " : s t r i n g
List Constructors
Example1.24. Empty Lists - n u l l l;
val it = f a l s e : b o o l - n u l l [];
val it = t ru e : b o o l
Example1.25. Construction and Concatenation - 9 : : l;
val it = [9 ,2 ,3 ,5] : int l i s t - [true,f a l s e] @ [false,tr u e];
val it = [true,false,false,t r u e] : b o o l l i s t
List Operations
Example1.26. Head and Tail - val l = [2 ,3 ,2+3];
val l = [2 ,3 ,5] : int l i st - hd l;
val it = 2 : int
- tl l;
val it = [3 ,5] : int l i s t
Pattern Matching
Example1.27. Pattern Matching and Lists - fun b i g a n d [] = t r ue
| b i g a n d (h: :t) = h a n d a l s o b i g a n d t;
val b i g a n d = fn : b o o l l is t - > b o o l
Pairs
Example1.28. Pair Functions - val p = (2 ,3) ;
val p = (2 ,3) : int * int - fst p;
val it = 2 : int
- snd p;
val it = 3 : int
Records
Example1.29. Date Record
val d a t e = {day=4 ,m o n t h=" f e b r u a r y ",y e a r=1 9 6 7 } : {day:int, m o n t h:string, y e a r:int}
- val {day=d,m o n t h=m,y e a r=y} = d a t e; val d = 4 : int
val m = " f e b r u a r y " : s t r i n g val y = 1 9 67 : int
- #m o n t h d a t e;
val it = " f e b r u a r y " : s t r i n g
Polymorphism
Example1.30. Head Function - hd [2 ,3];
val it = 2 : int
- hd [true,f a l s e];
val it = t ru e : b o o l
Problem1.31. What is the type ofhd? int list ->int or bool list ->bool
Polymorphism
Example1.32. Type of Head Function - hd;
val it = fn : ’ a l i s t -> ’a
Example1.33. Polymorphic Head Function
I head function has both types
I ’ais a type variable.
I hdcan have any type of the formσlist ->σ (whereσis an SML type)
Type Inference
Example1.34. Mapping Function - fun map f l =
if (n u l l l) t h e n []
e l s e f(hd l): :(map f (tl l) ) ;
val map = fn : (’ a - > ’b) - > ’ a l i s t - > ’b l i s t - map (fn x= >0) ;
val it = fn : ’ a l i s t -> int l i s t
Fact1.35. ML Type Inference SML infers the most general type.
Standard List Operations
Example1.36. Mapping - fun map f [] = []
| map f (h: :t) = f h : : map f t;
val (’a , ’b) map = fn : (’ a - > ’b) - > ’ a l i s t - > ’b l i s t
Example1.37. Filtering - fun f i l t e r P [] = []
| f i l t e r P (h: :t) = if P h t h e n h: :f i l t e r P t e l s e f i l t e r P t; val ’ a f i l t e r = fn : ( ’a - > b o o l) - > ’ a l i s t - > ’a
l i s t
Type Inference
Example1.38. Function Composition - fun c o m p f g x = f(g x) ;
val c o m p = fn:(’ a - > ’b) - > (’ c - > ’a) - > ’ c - > ’b - c o m p n u l l (map (fn y= > y+1) ) ;
val it = fn : int l i s t - > b o o l
Some System Functions
Example1.39. Load a file calledfile.sml - use;
val it = fn : s t r i n g - > u n i t - use " f i l e . sml ";
[o p e n i n g f i l e.sml] ...
Key Commands
I terminate the session:<Ctrl>D
I interrupt:<Ctrl>C
Tuples
Example1.40. Tuples - val p a i r = (2 ,3) ;
> val p a i r = (2 , 3) : int * int - val t r i p l e = (2 ,2.0 ," 2 ") ;
> val t r i p l e = (2 , 2.0 , " 2 ") : int * r e a l * s t r i n g - val p a i r s _ o f _ p a i r s = ((2 ,3) ,(2.0 ,3.0) ) ;
> val p a i r s _ o f _ p a i r s = ((2 , 3) , (2.0 , 3 . 0 ) ) : (int * int) * (r e al * r e a l)
Example1.41. Unit Type - val n u l l _ t u p l e = () ;
Accessing Components
Example1.42. Navigating to the Position - val xy1 = #1 p a i r s _ o f _ p a i r s;
> val xy1 = (2 , 3) : int * int - val y1 = #2 (#1 p a i r s _ o f _ p a i r s) ;
> val y1 = 3 : int
Example1.43. Using Pattern Matching
- val ((x1,y1) ,(x2,y2) ) = p a i r s _ o f _ p a i r s;
> val x1 = 2 : int
val y1 = 3 : int
val x2 = 2.0 : r e a l val y2 = 3.0 : r e a l
Pattern Matching
Example1.44. Granularity
- val ((x1,y1) ,xy2) = p a i r s _ o f _ p a i r s;
> val x1 = 2 : int
val y1 = 3 : int
val xy2 = (2.0 , 3 . 0 ) : r ea l * r e a l Example1.45. Wildcard Pattern
- val ((_ ,y1) ,(_ ,_) ) = p a i r s _ o f _ p a i r s;
> val y1 = 3 : int
- val ((_ ,y1) ,_) = p a i r s _ o f _ p a i r s;
Pattern Matching
Example1.46. Value Patterns
- val 0 = 1 -1;
- val (0 ,x) = (1 -1 ,34) ;
> val x = 34 : int - val (0 ,x) = (2 -1 ,34) ;
! U n c a u g h t e x c e p t i o n:
! B i n d
Binding Values
General Rules
I The variable bindingval var =valis irreducible.
I The wildcard bindingval _ =valis discarded.
I The tuple bindingval(pat1, ... , patN)=(val1, ... , valN )is reduced to
val p a t 1 = v a l N ...
val p a t N = v a l N
Clausal Function Expressions
Example1.47. Clausal Function Expressions - fun not t r u e = f a l s e
| not f a l s e = t r u e;
> val not = fn : b oo l - > b o o l
Redundant Cases
Example1.48. Redundant Cases - fun not T r u e = f a l s e
| not F a l s e = t r u e;
! W a r n i n g: s o m e c a s e s are u n u s e d in t h i s m a t c h.
> val ’ a not = fn : ’a - > b o o l - not f a l s e;
> val it = f a l s e : b o o l - not 3;
> val it = f a l s e : b o o l
Fact1.49. Redundant Cases are always a mistake!
Inexhaustive Matches
Example1.50. Inexhaustive Matches
fun f i r s t _ t e n 0 = t r u e | f i r s t _ t e n 1 = t r u e | f i r s t _ t e n 2 = t r u e
| f i r s t _ t e n 3 = t r u e | f i r s t _ t e n 4 = t r u e | f i r s t _ t e n 5 = t r u e
| f i r s t _ t e n 6 = t r u e | f i r s t _ t e n 7 = t r u e | f i r s t _ t e n 8 = t r u e
| f i r s t _ t e n 9 = t r u e;
! W a r n i n g: p a t t e r n m a t c h i n g is not e x h a u s t i v e
> val f i r s t _ t e n = fn : int - > b o o l - f i r s t _ t e n 5;
> val it = t r u e : bo o l f i r s t _ t e n ~1;
! U n c a u g h t e x c e p t i o n: M a t c h
Fact1.51. Inexhaustive Matches may be a problem.
Catch-All Clauses
Example1.52. Catch-All Clauses
fun f i r s t _ t e n 0 = t r u e | f i r s t _ t e n 1 = t r u e | f i r s t _ t e n 2 = t r u e
| f i r s t _ t e n 3 = t r u e | f i r s t _ t e n 4 = t r u e | f i r s t _ t e n 5 = t r u e
| f i r s t _ t e n 6 = t r u e | f i r s t _ t e n 7 = t r u e | f i r s t _ t e n 8 = t r u e
| f i r s t _ t e n 9 = t r u e | f i r s t _ t e n _ = f a l s e;
> val f i r s t _ t e n = fn : int - > b o o l
Overlapping Cases
Example1.53. Overlapping Cases - fun f o o 1 1 _ = 1
| f o o 1 _ 1 = 2
| f o o 1 _ _ = 0;
> val f o o 1 = fn : int - > int - > int - fun f o o 2 _ 1 = 1
| f o o 2 1 _ = 2
| f o o 2 _ _ = 0;
> val f o o 2 = fn : int - > int - > int - f o o 1 1 1;
> val it = 1 : int - f o o 2 1 1;
> val it = 1 : int
Recursively Defined Functions
Example1.54. Recursively Defined Function - fun f a c t o r i a l 0 = 1
| f a c t o r i a l n = n * f a c t o r i a l (n-1) ;
> val f a c t o r i a l = fn : int - > int - val rec f a c t o r i a l = fn
Example1.55. Recursively Defined Lambda Abstraction - val rec f a c t o r i a l =
fn 0 = > 1
| n = > n * f a c t o r i a l (n-1) ;
Mutual Recursion
Example1.56. Mutual Recursion - fun e v e n 0 = t r u e
| e v e n n = odd (n-1) and odd 0 = f a l s e
| odd n = e v en (n-1) ;
> val e v e n = fn : int - > b o o l val odd = fn : int - > bo o l - (e v e n 5 ,odd 5) ;
> val it = (false, t ru e) : b o o l * b o o l
Simple data Types: Type Abbreviations
type
Keyword
I type abbreviations
I record definitions
Example1.57. Type Abbreviation - t y p e b o o l P a i r = b o o l * b o o l;
> t y p e b o o l P a i r = b o o l * b o o l - (true,t r u e):b o o l P a i r;
> val it = (true, t r ue) : b o o l * b o o l
Defining a Record Type
Example1.58. Record - t y p e h y p e r l i n k =
{ p r o t o c o l : string, a d d r e s s : string, d i s p l a y : s t r i n g };
> t y p e h y p e r l i n k = {a d d r e s s : string, d i s p l a y : string , p r o t o c o l : s t r i n g}
- val h o l _ w e b p a g e = { p r o t o c o l=" h t t p ",
a d d r e s s=" rsg . i n f o r m a t i k . uni - kl . de / t e a c h i n g / hol ", d i s p l a y=" HOL - C o u r s e " };
> val h o l _ w e b p a g e = {
a d d r e s s = " rsg . i n f o r m a t i k . uni - kl . de / t e a c h i n g / hol ", d i s p l a y = " HOL - C o u r s e ",
p r o t o c o l = " h t t p "}
:{a d d r e s s : string, d i s p l a y : string, p r o t o c o l :
Accessing Record Components
Example1.59. Type Abbreviation
- val {p r o t o c o l=p, d i s p l a y=d, a d d r e s s=a } = h o l _ w e b p a g e;
> val p = " h t t p " : s t r i n g
val d = " HOL - C o u r s e " : s t r i n g
val a = " rsg . i n f o r m a t i k . uni - kl . de / t e a c h i n g / hol " : s t r i n g
- val {p r o t o c o l=_ , d i s p l a y=_ , a d d r e s s=a } = h o l _ w e b p a g e;
> val a = " rsg . i n f o r m a t i k . uni - kl . de / t e a c h i n g / hol " : s t r i n g
Accessing Record Components (cont.)
- val {a d d r e s s=a, ...} = h o l _ w e b p a g e;
> val a = " rsg . i n f o r m a t i k . uni - kl . de / t e a c h i n g / hol " : s t r i n g
- val {address, ...} = h o l _ w e b p a g e;
> val a d d r e s s = " rsg . i n f o r m a t i k . uni - kl . de / t e a c h i n g / hol
" : s t r i n g
Defining Really New Data Types
datatype
Keyword
programmer-defined (recursive) data types, introduces
I one or more new type constructors
I one or more new value constructors
Non-Recursive Data Type
Example1.60. Non-Recursive Datatype - d a t a t y p e t h r e e v a l = TT | UU | FF;
> New t y p e n a m e s: =t h r e e v a l d a t a t y p e t h r e e v a l =
(t h r e e v a l,{con FF : t h r e e v a l, con TT : t h r e e v a l, con UU : t h r e e v a l})
con FF = FF : t h r e e v a l con TT = TT : t h r e e v a l con UU = UU : t h r e e v a l - fun n o t 3 TT = FF
| n o t 3 UU = UU
| n o t 3 FF = TT;
> val n o t 3 = fn : t h r e e v a l - > t h r e e v a l - n o t 3 TT;
Parameterised Non-Recursive Data Types
Example1.61. Option Type
- d a t a t y p e ’ a o p t i o n = N O N E | S O M E of ’a;
> New t y p e n a m e s: =o p t i o n d a t a t y p e ’ a o p t i o n =
( ’a option,{con ’ a N O N E : ’a option, con ’ a S O M E : ’ a - > ’ a o p t i o n })
con ’a N O N E = N O N E : ’ a o p t i o n con ’a S O M E = fn : ’ a -> ’a o p t i o n
I constantNONE
I values of the formSOMEv (wherev has the type’a)
Option Types
Example1.62. Option Type - fun r e c i p r o c a l 0.0 = N O N E
| r e c i p r o c a l x = S O M E ( 1 . 0 /x)
> val r e c i p r o c a l = fn : r e a l - > r e al o p t i o n - fun i n v _ r e c i p r o c a l N O N E = 0.0
| i n v _ r e c i p r o c a l (S O M E x) = 1 . 0 /x;
> val i n v _ r e c i p r o c a l = fn : r e a l o p t i o n - > r e a l - fun i d e n t i t y x = i n v _ r e c i p r o c a l (r e c i p r o c a l x) ;
> val i d e n t i t y = fn : r e a l - > r e a l - i d e n t i t y 4 2 . 0 ;
> val it = 4 2 . 0 : re a l - i d e n t i t y 0 . 0 ;
> val it = 0.0 : r ea l
Recursive Data Types
Example1.63. Binary Tree - d a t a t y p e ’ a t r e e = E m p t y |
N o d e of ’a t r e e * ’ a * ’a t r e e;
> New t y p e n a m e s: =t r e e d a t a t y p e ’ a t r e e = ( ’a tree,
{con ’ a E m p t y : ’a tree,
con ’ a N o d e : ’a t r e e * ’ a * ’a t r e e - > ’ a t r e e }) con ’a E m p t y = E m p t y : ’ a t r e e
con ’a N o d e = fn : ’ a tr e e * ’a * ’ a t r e e - > ’a t r e e
I is an empty binary tree
Functions and Recursive Data Types
Example1.64. Binary Tree - fun t r e e H e i g h t E m p t y = 0
| t r e e H e i g h t (N o de (l e f t S u b t r e e, _ , r i g h t S u b t r e e) )
=
1 + max(t r e e H e i g h t l e f t S u b t r e e, t r e e H e i g h t r i g h t S u b t r e e) ;
> val ’ a t r e e H e i g h t = fn : ’a t r e e - > int
Mutually Recursive Datatypes
Example1.65. Binary Tree - d a t a t y p e ’ a t r e e =
E m p t y |
N o d e of ’a * ’ a f o r e s t and ’a f o r e s t =
N o n e |
T r e e of ’ a t r e e * ’a f o r e s t;
> New t y p e n a m e s: =forest, =t r e e ...
Abstract Syntax
Example1.66. Defining Expressions - d a t a t y p e e x p r =
N u m e r a l of int | P l u s of e x p r * e x p r | T i m e s of e x p r * e x p r;
> New t y p e n a m e s: =e x p r d a t a t y p e e x p r =
(expr,
{con N u m e r a l : int - > expr, con P l u s : e x p r * e x p r - > expr, con T i m e s : e x p r * e x p r -> e x p r}) con N u m e r a l = fn : int - > e x p r con P l u s = fn : e x p r * e x p r - > e x p r con T i m e s = fn : e x p r * e x p r - > e x p r
Abstract Syntax
Example1.67. Evaluating Expressions - fun e v a l (N u m e r a l n) = N u m e r a l n
| e v a l (P l u s(e1,e2) ) =
let val N u m e r a l n1 = e v a l e1 val N u m e r a l n2 = e v a l e2 in N u m e r a l(n1+n2) end
| e v a l (T i m e s (e1,e2) ) =
let val N u m e r a l n1 = e v a l e1
val N u m e r a l n2 = e v a l e2 in N u m e r a l(n1*n2) end;
> val e v a l = fn : ex p r - > e x p r
- e v a l( P l u s( N u m e r a l 2 , T i m e s( N u m e r a l 5 , N u m e r a l 8 )
Modules: Structuring ML Programs
Modules
I structuring programs into separate units
I program units in ML:structures
I contain a collection of types, exceptions and values (incl. functions)
I parameterised units possible
I composition of structures mediated bysignatures
Structures
Purpose
I structures = implementation
Example1.68. Structure s t r u c t u r e Q u e u e = s t r u c t
t y p e ’ a q u e u e = ’a l i st * ’ a l i s t val e m p t y = ( nil , nil )
fun i n s e r t ( x , ( bs , fs ) ) = ( x: :bs , fs ) e x c e p t i o n E m p t y
fun r e m o v e ( nil , nil ) = r a i s e E m p t y
| r e m o v e ( bs , f: :fs ) = ( f , ( bs , fs ) )
Accessing Structure Components
Identifier Scope
I components of a structure: local scope
I must be accessed by qualified names
Example1.69. Accessing Structure Components - Q u e u e.e m p t y;
> val (’a , ’b) it = ([] , []) : ’ a l i s t * ’b li s t - o p e n Q u e u e;
> ... - e m p t y;
> val (’a , ’b) it = ([] , []) : ’ a l i s t * ’b li s t
Accessing Structure Components
Usage of
openI open a structure to incorporate its bindings directly
I cannot open two structures with components that share a common names
I prefer to use open inletandlocalblocks
Signatures
Purpose
I signatures = interface
Example1.70. Signature
s i g n a t u r e Q U E U E = sig
t y p e ’ a q u e u e e x c e p t i o n E m p t y val e m p t y : ’a q u e u e
val i n s e r t: ’ a * ’a q u e u e - > ’ a q u e u e val r e m o v e: ’a q u e u e - > ’ q * ’a q u e u e end
Signature Ascription
Transparent Ascription
I descriptive ascription
I extract principal signature
I always existing for well-formed structures
I most specific description
I everything needed for type checking
I source code needed
Opaque Ascription
I restrictive ascription
Opaque Ascription
Example1.71. Opaque Ascription
s t r u c t u r e Q u e u e :> Q U E U E s t r u c t
t y p e ’ a q u e u e = ’a l i st * ’ a l i s t val e m p t y = ( nil , nil )
fun i n s e r t ( x , ( bs , fs ) ) = ( x: :bs , fs ) e x c e p t i o n E m p t y
fun r e m o v e ( nil , nil ) = r a i s e E m p t y
| r e m o v e ( bs , f: :fs ) = ( f , ( bs , fs ) )
| r e m o v e ( bs , nil )= r e m o v e ( nil , rev bs ) end
Signature Matching
Conditions
I structure may provide more components
I structure may provide more general types than required
I structure may provide a concrete datatype instead of a type
I declarations in any order
Modular Compilation in Moscow ML
Compiler mosmlc
I save structure Foo to fileFoo.sml
I compile module:mosmlc Foo.sml
I compiled interface inFoo.uiand compiled bytecodeFoo.uo
I load moduleload "Foo.ui"
- l o a d " Q u e u e ";
> val it = () : u n it - o p e n Q u e u e;
> t y p e ’ a q u e u e = ’a l i s t * ’ a l is t
val ( ’a, ’ b ) i n s e r t = fn : ’a * (’ a li s t * ’b) - > ’ a l i s t * ’b
exn E m p t y = E m p t y : exn
val (’a , ’b) e m p t y = ([] , []) : ’ a l i s t * ’b l i s t
Implementing a Simple Theorem Prover: Overview
Theorem Prover
I theorem prover implements a proof system
I used for proof checking and automated theorem proving
Goals
I build your own theorem prover for propositional logic
I understanding the fundamental structure of a theorem prover
Data Types
Data Types of a Theorem Prover
I formulas, terms and types
I axioms and theorems
I deduction rules
I proofs
Formulas, Terms and Types
Propositional Logic
I each term is a formula
I each term has the typeB
Data Type Definition
d a t a t y p e T e r m =
V a r i a b l e of s t r i n g | C o n s t a n t of b o o l | N e g a t i o n of T e r m |
C o n j u n c t i o n of T e r m * T e r m |
Syntactical Operations on Terms
Determining the Topmost Operator
fun i s V a r (V a r i a b l e x) = t ru e
| i s V a r _ = f a l s e;
fun i s C o n s t (C o n s t a n t b) = t r u e
| i s C o n s t _ = f a l s e;
fun i s N e g (N e g a t i o n t1) = tr u e
| i s N e g _ = f a l s e;
fun i s C o n (C o n j u n c t i o n (t1,t2) ) = t r u e
| i s C o n _ = f a l s e;
fun i s D i s (D i s j u n c t i o n (t1,t2) ) = t r u e
| i s D i s _ = f a l s e;
fun i s I m p (I m p l i c a t i o n (t1,t2) ) = t r u e
| i s I m p _ = f a l s e;
Syntactical Operations on Terms
Composition
I combine several subterms with an operator to a new one
Composition of Terms
fun m k V a r s1 = V a r i a b l e s1;
fun m k C o n s t b1 = C o n s t a n t b1;
fun m k N e g t1 = N e g a t i o n t1;
fun m k C o n (t1,t2) = C o n j u n c t i o n(t1,t2) ; fun m k D i s (t1,t2) = D i s j u n c t i o n(t1,t2) ; fun m k I m p (t1,t2) = I m p l i c a t i o n(t1,t2) ;
Syntactical Operations on Terms
Decomposition
I decompose a term
Decomposition of Terms
e x c e p t i o n S y n t a x E r r o r;
fun d e s t N e g (N e g a t i o n t1) = t1
| d e s t N e g _ = r a i s e S y n t a x E r r o r ;
fun d e s t C o n (C o n j u n c t i o n (t1,t2) ) = (t1,t2)
| d e s t C o n _ = r a i s e S y n t a x E r r o r ;
fun d e s t D i s (D i s j u n c t i o n (t1,t2) ) = (t1,t2)
| d e s t D i s _ = r a i s e S y n t a x E r r o r ;
fun d e s t I m p (I m p l i c a t i o n (t1,t2) ) = (t1,t2)
| d e s t I m p _ = r a i s e S y n t a x E r r o r ;
Term Examples
Example1.72. Terms
I t1=a∧b∨ ¬c;
I t2=true∧(x ∧y)∨ ¬z;
I t3=¬((a∨b)∧ ¬c) val t1 = D i s j u n c t i o n(
C o n j u n c t i o n(V a r i a b l e " a ",V a r i a b l e " b ") , N e g a t i o n(V a r i a b l e " c ") ) ;
val t2 = D i s j u n c t i o n(
C o n j u n c t i o n(C o n s t a n t true,
C o n j u n c t i o n (V a r i a b l e " x ", V a r i a b l e " y ") ) ,
N e g a t i o n(V a r i a b l e " z ") ) ;
Theorems
Data Type Definition
d a t a t y p e T h e o r e m =
T h e o r e m of T e r m l i s t * Te r m;
Syntactical Operations
fun a s s u m p t i o n s (T h e o r e m (assums,c o n c l) ) = a s s u m s; fun c o n c l u s i o n (T h e o r e m (assums,c o n c l) ) = c o n c l; fun m k T h e o r e m(assums,c o n c l) = T h e o r e m(assums,c o n c l) ; fun d e s t T h e o r e m (T h e o r e m (assums,c o n c l) ) = (assums,
c o n c l) ;
Rules
Data Type Definition
d a t a t y p e R u l e =
R u l e of T h e o r e m l i s t * T h e o r e m;
Application of Rules
Application of Rules
I form a new theorem from several other theorems
Application (Version 1)
e x c e p t i o n D e d u c t i o n E r r o r; fun a p p l y R u l e r u l e t h m s =
let
val R u l e (prem,c o n c l) = r u l e in
if p r e m=t h m s t h e n c o n c l e l s e r a i s e D e d u c t i o n E r r o r end;
Application of Rules
Application of Rules
I premises and given theorems do not need to be identical
I premises only need to be in the given theorems
Application (Version 2)
fun mem x [] = f a l s e
| mem x (h: :t) = (x=h) o r e l s e (mem x t) ; fun s u b l i s t [] l2 = t r u e
| s u b l i s t (h1: :t1) l2 = (mem h l2) a n d a l s o (s u b l i s t t1 l2) ;
fun a p p l y R u l e r u l e t h m s =
Application of Rules
Example1.73. Rule Application
val a x i o m 1 = T h e o r e m( [] , (V a r i a b l e " a ") ) ;
val a x i o m 2 = T h e o r e m( [] , I m p l i c a t i o n((V a r i a b l e " a ") ,(
V a r i a b l e " b ") ) ) ;
val a x i o m 3 = T h e o r e m( [] , I m p l i c a t i o n((V a r i a b l e " b ") ,(
V a r i a b l e " c ") ) ) ; val m o d u s P o n e n s =
R u l e(
[T h e o r e m( [] , I m p l i c a t i o n((V a r i a b l e " a ") ,(
V a r i a b l e " b ") ) ) ,
T h e o r e m( [] , (V a r i a b l e " a ") ) ] ,
T h e o r e m( [] , (V a r i a b l e " b ") ) ) ;
Application of Rules
Example1.74. Rule Application
val t h m 1 = a p p l y R u l e m o d u s P o n e n s [axiom1,a x i o m 2];
val t h m 2 = a p p l y R u l e m o d u s P o n e n s [thm1,a x i o m 3];
Problem
I axioms and rules should work for arbitrary variables
I axiom scheme, rule scheme
I definition of substitution and unification needed
Support Functions
Support Functions
fun i n s e r t x l = if mem x l t h e n l e l s e x: :l; fun a s s o c [] a = N O N E
| a s s o c ((x,y): :t) a = if (x=a) t h e n S O M E y e l s e a s s o c t a;
fun o c c u r s v (w as V a r i a b l e _) = (v=w)
| o c c u r s v (C o n s t a n t b) = f a l s e
| o c c u r s v (N e g a t i o n t) = o c c u r s v t
| o c c u r s v (C o n j u n c t i o n (t1,t2) ) = o c c u r s v t1 o r e l s e o c c u r s v t2
| o c c u r s v (D i s j u n c t i o n (t1,t2) ) = o c c u r s v t1 o r e l s e o c c u r s v t2
| o c c u r s v (I m p l i c a t i o n (t1,t2) ) = o c c u r s v t1
Substitution
Substitution
fun s u b s t t h e t a (v as V a r i a b l e _) =
(c a s e a s s o c t h e t a v of N O N E = > v | S O M E w
= > w)
| s u b s t t h e t a (C o n s t a n t b) = C o n s t a n t b
| s u b s t t h e t a (N e g a t i o n t) = N e g a t i o n(s u b s t t h e t a t)
| s u b s t t h e t a (C o n j u n c t i o n (t1,t2) ) =
C o n j u n c t i o n(s u b s t t h e t a t1, s u b s t t h e t a t2)
| s u b s t t h e t a (D i s j u n c t i o n (t1,t2) ) =
D i s j u n c t i o n(s u b s t t h e t a t1, s u b s t t h e t a t2)
| s u b s t t h e t a (I m p l i c a t i o n (t1,t2) ) =
Substitution
Example1.75. Substitution
val t h e t a 1 = [(V a r i a b l e " a ",V a r i a b l e " b ") ,(V a r i a b l e " b
",C o n s t a n t t r u e) ];
Unification
Definition1.76. Matching: A termmatchesanother if the latter can be obtained by instantiating the former.
matches(M,N)⇔ ∃θ.subst(θ,M) =N
Definition1.77. Unifier, Unifiability: A substitution is aunifierof two terms, if it makes them equal.
unifier(θ,M,N)⇔subst(θ,M) =subst(θ,N) Two terms are unifiable if they have a unifier.
Unification Algorithm
General Idea
I traverse two terms in exactly the same way
I eliminating as much common structure as possible
I things actually happen when a variable is encountered (in either term)
I when a variable is encoutered, make a binding with the
corresponding subterm in the other term, and substitute through
I important: making a binding(x,M)wherex occurs inMmust be disallowed since the resulting substitution will not be a unifier occur check.
Unification Algorithm
Unification
e x c e p t i o n U n i f i c a t i o n E x c e p t i o n;
fun u n i f y l [] [] t h e t a = t h e t a
| u n i f y l ((v as V a r i a b l e _): :L) (M: :R) t h e t a = if v=M t h e n u n i f y l L R t h e t a
e l s e if o c c u r s v M t h en r a i s e U n i f i c a t i o n E x c e p t i o n
e l s e u n i f y l (map (s u b s t [(v,M) ]) L) (map (s u b s t [(v,M) ]) R) (c o m b i n e S u b s t [(v,M) ] t h e t a)
| u n i f y l L1 (L2 as (V a r i a b l e _: :_) ) t h e t a =
Unification Algorithm
...
| u n i f y l (N e g a t i o n tl: :L) (N e g a t i o n tr: :R) t h e t a = u n i f y l (tl: :L) (tr: :R) t h e t a
| u n i f y l (C o n j u n c t i o n (tl1,tl2): :L) (C o n j u n c t i o n (tr1 ,tr2): :R) t h e t a =
u n i f y l (tl1: :tl2: :L) (tr1: :tr2: :R) t h e t a
| u n i f y l (D i s j u n c t i o n (tl1,tl2): :L) (D i s j u n c t i o n (tr1 ,tr2): :R) t h e t a =
u n i f y l (tl1: :tl2: :L) (tr1: :tr2: :R) t h e t a
| u n i f y l (I m p l i c a t i o n (tl1,tl2): :L) (I m p l i c a t i o n (tr1 ,tr2): :R) t h e t a =
u n i f y l (tl1: :tl2: :L) (tr1: :tr2: :R) t h e t a
| u n i f y l _ _ _ = r a i s e U n i f i c a t i o n E x c e p t i o n;
Combining Substitutions
Combining Substitutions
fun c o m b i n e S u b s t t h e t a s i g m a =
let val (dsigma,r s i g m a) = L i s t P a i r.u n z i p s i g m a val s i g m a 1 = L i s t P a i r.zip(dsigma,(map (s u b s t
t h e t a) r s i g m a) )
val s i g m a 2 = L i s t.f i l t e r (op < >) s i g m a 1
val t h e t a 1 = L i s t.f i l t e r (fn (a,_) = > not (mem a d s i g m a) ) t h e t a
in
s i g m a 2 @ t h e t a 1 end;
Summary
I programming in Standard ML
I evaluation and bindings
I defining functions
I standard data types
I type inference
I case analysis and pattern matching
I data type definitions
I modules
I primitive theorem prover kernel
I terms
I theorems
I rules
I substitution
I unification