-- ========================================================== --> CafeOBJ code for lecture01 -- ========================================================== --> Peano style natural numbers mod! PNAT { [ Nat ] op 0 : -> Nat {constr} . op s_ : Nat -> Nat {constr} . -- an built-in equality predicate _=_ is -- available for all sorts and -- op _=_ : Nat Nat -> Bool {comm} . and -- eq (X:Nat = X) = true . -- are declared automatically eq (0 = s(Y:Nat)) = false . eq (s(X:Nat) = s(Y:Nat)) = (X = Y) . } -- "mod! PNAT {" indicates start of definition of module -- named "PNAT". The definition ends at "}". -- "[ Nat ]" is a declaration of a sort (i.e. set of -- objects) named "Nat". -- "op 0 : -> Nat {constr} ." is a declaration of operator -- named "0" with no argument and return value of sort -- "Nat". That is, "0" is a constant of sort "Nat". "0" -- has an attribute of constructor indicated by -- "{constr}". The last "." can be omitted. -- "op s_ : Nat -> Nat {constr} ." is a declaration of -- constructor operator named "s_" with an argument of sort -- "Nat" and return value of sort "Nat". "_" in "s_" -- indicts the position where the argument placed. -- Notice that the first "=" of "eq (0 = s(Y:Nat)) = false ." is -- an equality operator on the sort "Nat", but the second -- "=" is for declaring an equation in CafeOBJ language. -- "X:Nat" is an on-the-fly declaration of variable "X" and the scope -- of this variable ends at the end of this equation. "." at -- the end and a space before it is must. -- "{comm}" indicates that the binary operator "_=_" is -- commutative operator, i.e. -- ((X:Nat = Y:Nat) = (Y = X)) -- holds. --> PNAT with plus _+_ operation mod! PNAT+ { pr(PNAT) op _+_ : Nat Nat -> Nat {r-assoc} . vars X Y : Nat . eq 0 + Y = Y . eq (s X) + Y = s(X + Y) . } -- "pr(PNAT)" indicates the importation of module "PNAT" -- into this module with the importation mode of "pr" -- (i.e. protecting). "pr" indicates that the module -- "PNAT+" refers the module "PNAT" as a sub-module, and can -- use any entities declared in the module "PNAT". -- "{r-assoc}" indicates that the operator "_+_" associate -- to right. This is just for parsing terms. -- "vars X Y : Nat ." is a declaration of variables "X" and -- "Y" of sort "Nat". The scope of these variables ends at -- the end of the module. "." at the end can be omitted. -- ========================================================== --> special charactors of CafeOBJ -- ========================================================== -- Eight charactors "(" ")" "," ";" "[" "]" "{" "}" are -- self-terminating characters of CafeOBJ. A -- self-terminating charactor is a printable ASCII character -- which by itself constitutes a token. You do not need to -- put spaces before and after these characters. -- Two charactors of "(" ")" are meta-charactors of CafeOBJ -- system, and should be used only for grouping -- terms/expressions. These charactors can not be used in -- any kind of identifiers. ** ========================================================== --> proof scores for the properties about _+_ ** ========================================================== -- ========================================================== --> Proof score for righ zero property: --> (N:Nat + 0 = N) -- ========================================================== **> Proof of (N:Nat + 0 = N) by induction on N:Nat **> induction base case: -- opening module PNAT+ to make use of all its contents -- set N = 0 open PNAT+ . -- "." is necessary red 0 + 0 = 0 . close **> induction step case: -- opening module PNAT+ to make use of all its contents open PNAT+ . **> declare that a fresh constant n stands for any element **> in Nat op n : -> Nat . **> induction hypothesis: eq n + 0 = n . **> induction step proof for (s n): red s n + 0 = s n . close **> QED {end of proof} -- ========================================================== -- "open PNAT+ ." opens the module "PNAT+" and creates a -- temporal module which can use all entities in -- "PNAT+". The created temporal module is discarded by -- "close". -- "op n : -> Nat ." is an operator declaration inside -- "open" and "close", and the last "." is a must. This is -- different from an operator declaration inside module -- definition. -- "red 0 + 0 = 0 ." and "red s n + 0 = s n ." are reduction -- commands, and return the most simplified expression of "0 -- + 0 = 0" and "s n + 0 = s n" by using all avairable -- equations of the module "PNAT+" as rewrite rules from -- left to write. -- ========================================================== --> Proof score for associativity of (_ + _) --> (N1:Nat + N2:Nat) + N3:Nat = N1 +(N2 + N3) -- ========================================================== **> Proof of associativity: **> (N1:Nat + N2:Nat) + N3:Nat = N1 +(N2 + N3) **> by induction on N1 {**> induction base case: open PNAT+ . red 0 + (`n2:Nat + `n3:Nat) = (0 + `n2) + `n3 . close **> induction step case: open PNAT+ . **> declare that the constant n1 stands for any Nat value op n1 : -> Nat . **> induction hypothesis: eq (n1 + N2:Nat) + N3:Nat = n1 + (N2 + N3) . **> induction step proof for (s n1): red ((s n1) + `n2:Nat) + `n3:Nat = (s n1) + (`n2 + `n3) . close **> QED {end of proof} -- ========================================================== -- On-the-fly declarations in red (reduction) command like -- "`n2:Nat" and "`n3:Nat" are declarations of "fresh -- constants" whoes scopes end at the end of the reduction -- command. It is recommended to use names that start -- with ` for declaring fresh constants in reduction -- commands. -- ========================================================== --> comments in CafeOBJ codes -- ========================================================== -- line starts with "-- " or "** " is a comment line --> line starts with "--> " and "**> " are comment lines with --> echo backs from CafeOBJ system. That is, the system --> print out these lines if this file is inputed into the --> system. -- Text not containing charactore " and enclosed with " and -- " is a comment. -- ========================================================== --> parsing term with precedences and {r-assoc} attribute -- ========================================================== -- selecting PNAT select PNAT parse s s 0 . reduce s s 0 . -- "parse s s 0 ." is a command to parse the term "s s 0" open PNAT+ . parse s 0 + 0 . parse s 0 + 0 = s 0 + 0 . parse s 0 + 0 = s s 0 + s 0 + 0 . show tree describe op (s _) describe op (_ + _) describe op (_ = _) sh ops sh op (s _) sh op (_ + _) sh op (_ = _) close -- It is better to put enough parentheses and make the term -- structure clear! Do not play with parsing with -- precedences too much! -- ========================================================== -- Order sorted Peano style natural numbers -- and error handling -- ========================================================== --> Order sorted Peano style natural numbers mod! PNATord { [Zero NzNat < Nat] op 0 : -> Zero {constr} . -- successor op s_ : Zero -> NzNat {constr} . op s_ : Nat -> NzNat {constr} . -- predecessor op p_ : NzNat -> Nat . eq p s N:Nat = N . -- equality over Nat eq (0 = s(N2:Nat)) = false . eq (s(N1:Nat) = s(N2:Nat)) = (N1 = N2) . } -- "[Zero NzNat < Nat]" indicates that the sort "Zero" and -- "NzNat" are included in the sort "Nat". --> error handling with ordered sorts open PNATord . -- (p 0) is a term of error sort parse p 0 . red p 0 . parse p s 0 . red p s 0 = 0 . parse p p s 0 . red p p s 0 . red p p s 0 = 0 . -- these reductions show examples of -- error handling with ordered sorts close -- ========================================================== --> Difference of _=_ and _==_ -- ========================================================== -- opening PNAT open PNAT . parse 0 = s 0 . red 0 = s 0 . op n : -> Nat . red n = n . red 0 = n . red 0 == n . close -- NAT is built-in module of natural numbers. The module -- NAT contains (1) sort Nat which is a set of infinite -- natural numbers, and (2) ordinary fundamental operations -- over Nat. -- EQL is built-in meta-module for making predicate _=_ -- available. This module is automatically imported like -- the module BOOL. -- Inspect EQL by the command: sh EQL mod! GOOD-POS{ pr(NAT) pred positive : Nat eq positive(N:Nat) = not(N = 0) . } mod! BAD-POS{ pr(NAT) pred positive : Nat eq positive(N:Nat) = not(N == 0) . } -- Proof scores for "positive(n) for all n in Nat" -- this is incorrect proof score because _==_ is used -- in BAD-POS open BAD-POS . op n : -> Nat . red positive(n) . close -- Proof scores for "positive(n) for all Nat n" -- this is correct proof score open GOOD-POS . op n : -> Nat . red positive(n) . close -- Proof scores for "positive(n) if ((n = 0) = false) -- this is correct proof score open GOOD-POS . op n : -> Nat . eq (n = 0) = false . red positive(n) . close -- ========================================================== --> end end end -- ==========================================================