STACK of E (LIFO list)
Algebraic Semantics (Guttag's Method)
STACK is the type we are defining
The list/stack contains elements of some type E
signatures (operations and types of parameters/return value)
new: --> STACK (canonical constructor)
push: STACK x E --> STACK (canonical constructor)
pop: STACK --> STACK
top: STACK --> E
size: STACK --> nat (naturals, int >=0 )
empty: STACK --> boolean
axioms (behavior)
size(new) = 0
size(push(S,e)) = size(S) + 1
empty(new) = true
empty(push(S,e)) = false
top(new) = error
top(push(S,e)) = e
pop(new) = new
pop(push(S,e)) = S
SML representation of the semantics
this version is stack of int... works on ints only
(* canonical ops are done as SML user-defined datatype *)
datatype STI =
New
| push of STI * int ;
(* non-canonical ops are done using partial function definitions,
more-or-less one per axiom
*)
fun size (New) = 0
| size (push(S,i)) = size(S)+1;
fun pop (New) = New
| pop (push(S,i)) = S ;
fun empty (New) = true
| empty (S) = (size(S)=0) ;
exception topEmptyStack;
fun top (New) = raise topEmptyStack
| top (push(S,i)) = i ;
(*---------------------------------------*)
(* test data points *)
(*---------------------------------------*)
val s0 = New;
val s1 = push(s0,10);
val s2 = push(s1,20);
val s3 = push(s2,30);
(*---------------------------------------*)
(* test cases *)
(*---------------------------------------*)
size(s2) = 2;
size(s0) = 0;
size(s3) = 3;
top(s2) = 20;
top(s1) = 10;
size(push(s3,40)) = size(s3) + 1;
size(push(s3,40)) = 4;
size(pop(s3)) = size(s3) - 1;
size(pop(s3)) = 2;
size(pop(s1)) = 0;
size(pop(New)) = 0;
top(pop(s3)) = 20;
top(pop(s2)) = 10;
top(pop(s1));
top(pop(push(push(pop(push(s3,40)),50),60))) = 50;
size(pop(push(push(pop(push(s3,40)),50),60))) = 4;
SML representation of the semantics
this version is stack of any type... the datatype defn is parameterized
datatype ('e) STACK =
New
| push of ('e) STACK * 'e ;
(* non-canonical ops are done using partial function definitions,
more-or-less one per axiom
*)
fun size (New) = 0
| size (push(S,i)) = size(S)+1;
fun pop (New) = New
| pop (push(S,i)) = S ;
fun empty (New) = true
| empty (S) = (size(S)=0) ;
exception topEmptyStack;
fun top (New) = raise topEmptyStack
| top (push(S,i)) = i ;