(* square : int -> int
REQUIRES: true
ENSURES: square(n) => n^2
*)
fun square (n : int) : int = n*n
Below shows execution sequence:
square 7
=> [environment where square was defined] (fn (n:int) => n * n) 7
=> [env.] [7/n] (n * n)
=> [env.] [7/n] (7 * n)
=> [env.] [7/n] (7 * 7)
=> [env.] [7/n] 49 = 49 // once we got a value, environment is not important
or write it simpler:
square 7 // this is also fine
=> 7 * 7
=> 49
(* even: int -> bool
REQUIRES: true
ENSURES: even k (tailedarror => to value) {true if k even; false if k odd}
fun even (k : int) : bool = (k mod 2) = 0
*)
In if e1 then e2 else e3 : t
, e2
and e3
has to be the same type t
.
Equivalently, in the following code e2
and e3
has to be the same type.
case e1 of
true => e2
| false => e3
If...then...else
is only good forbool
Always usecase
will ensure you don't make mistake
(* power: (int * int) -> int
REQUIRES: k >= 0
ENSURES: power (n, k) (tailedarror) n^k (where 0^0 = 1)
*)
fun power (n : int, 0 : int) : int = 1
| power (n, k) = n * power (n, k-1)
(* 3^7 = 3*3*3*3*3*3*3 *)
(* complexity: O(k) by recursive calls *)
fun power (n : int, 0 : int) : int = 1
| power (n, k) =
if even k
then square (power (n, k div 2))
else n * power (n, k-1)
(* 3^7 = 3(3(3*1)^2)^2 *)
(* complexity: O(log k) *)
Theorem: for all VALUES (because they might have on value) n:int, k:int where k>=0, power (n, k) |-> n^k Proof(1): By standard (weak) induction on k Base Case: k=0 WTS power (n, 0) |-> n^0 = 1 for all values n:int. power (n, 0) => 1 [first clause of power] Induction Step: prove k+1 holds using k hold induction hypothesis: power (n, k) -> n^k hold for all values n : int, for some fixed k >= 0 WTS: power (n, k+1) |-> n^{k+1} for all value n : int power (n, k+1) => n * power (n, k+1-1) [2nd clause] => n * power (n, k) [math] => n * n^k [induction hypothesis] => n^{k+1} [math] Since base case and inductive case are proved, the result follows by induction.
Proof(2): By strong induction on k Base Case: k=0 WTS power (n, 0) |-> n^0 = 1 for all values n:int. power (n, 0) => 1 [first clause of power] Induction Step: prove k hold using for all 0 <= k' < k, k' hold induction hypothesis: power (n, k) -> n^k hold for k' : int with 0 <= k' < k, and n : int WTS: power (n, k) |-> n^{k} for all value n : int power (n, k) => if even k then square (power (n, k div 2)) else n * power (n, k - 1) [2nd clause] case: k even: => square (power (n, k div 2)) [if-then-else] k = 2 * k' (for some k') and even k |=> true then k' = k/2, then k' < k [by math since k>0 and even] => square (power (n, k')) [math] => square (n^k') [IH] => n^k' * n^k' [by square] => n^k [math] case: k odd: => n * power (n, k-1) [if-then-else] ... (change k+1 to k)...
Structured induction is just induction but with code.
Type: t list (is a list for any type t)
Values: [v1, ..., vn] where each vi is a value of type t and n>= 0 - when n = 0, [] = nil
Expressions:
- []
or nil
- e :: es
(where e:t and es: t list)
- ::
is pronounced as "con" stands for concat
- val 1::[2, 3] = [1, 2, 3]
Type Checking rule:
- [] : t list
- e :: es : t list
if e : t
and es : t list
(*
length: int list -> int
REQUIRES: true
ENSURES: length L returns the length of L
*)
fun length ([] : int list) : int = 0
| length (x :: xs) = 1 + length xs
Theorem: length is total (ie. length L |-> something
, for all L : int list
)
Proof: by structure induction on L
Base Case: when L = []
WTS length [] |-> something
length []
=> 0 [first clause]
Inductive Step: when L = x::xs
for some value x:int
and xs:int list
IH: length xs |-> v for some v
WIS: length (x::xs) |-> v' for some v'
length (x::xs)
=> 1 + length xs [second clause]
=> 1 + v [IH]
=> (v + 1) [math]
let v' = v+1
, since v
is a type int
, v'
is value
Table of Content