THE ManTa SYSTEM 3.1


USER'S MANUAL
Written by Vladimir Támara Patiño.
2001

CONTENTS
1. INTRODUCTION
1.1. Rights

1.2. References 
2. INSTALLATION
3. CONFIGURATION
3.1. Initialization file 
3.2 Messages
3.3 Menus
3.4 Templates
4. THE MANTA SYSTEM 4.1  The interfaces
4.2 Types
4.3 Theorem Prover and rewriting motor
4.4 Generation of Code
APPENDIX A. EXAMPLES OF ADT
 

1. INTRODUCTION

ManTa is the name of a programming/specification language and also the name of a system to assist a user in writing programs in the ManTa language.
  This document describes the operation of the version 3.1 of the ManTa system, and gives a general overview of the ManTa language and the theory required to use the System.  More details about the language can be found in its formal specification [LangSpec] and more about its history in the ManTa website: http://manta.sourceforge.net.

1.1. Rights

This documentation is given to the public domain. Citation of the source is appreciated.

Some portions of the source code and documentation of ManTa are covered by the GPL, other parts belong to the public domain.

The code generated by ManTa has not copyright restrictions, the copy conditions can be imposed freely by the author of the ManTa specification, that originated the code.

1.2. References

[LangSpec] TÁMARA, Vladimir with ideas of Prof. Rodrigo Cardoso and Prof. Klaus Madlener Formal Description of the Manta 3 language. 2000. http://manta.sourcerforge.net/doc/formal3/index.html
[Tor91]     TORO, Victor Manuel. Organización y documentación de programas grandes en C 
            (ANSI), Memo de investigación 52, Circulación privada Centro de Documentación
            de la Facultad de Ingeniería de la Universidad de los Andes, 1991.

2. INSTALLATION


The distribution site of ManTa is http://manta.sourceforge.net, where you can download the most recent version (either as sources or binaries for some platforms).

If you download a binary distribution, just install it (after decompressing it, if necessary). The sources can be compiled in several variants of Unix (e.g Linux, SunOS, OpenBSD) as well as in DOS like systems (e.g Windows 95, Windows NT, DOS of 32bits --even without long name support). The precise instructions to compile them can be found along with the sources in the file INSTALL, here we present only a table that summarizes the features of ManTa in each type of platform:

FeatureUnixDos
I. Distribution
Preferred dist.sourcesbinaries
II. Compilation and tailoring of sources
Configuration methodconfigureedit makefile.dj
Compilationgcc,make,sedgcc (djggp), make, sed
Binaries (*)/usr/local/bin/manta/
Shared data (*)/usr/local/share/manta/manta/
Elisp data (*)/usr/local/share/emacs/site-lisp/manta/
Documentation (*)/usr/local/share/doc/manta/manta/
User directory~/.manta/manta/
III. Final Binaries
Configuration by final usersmanconfmanconf
Support several usersYesNo
Interfaces supportedCommand line, plain, emacsCommand line, plain, emacs
Support for several languagesYesYes
Compilers supportedgcc or cc, any makegcc (djgpp or cygnus), bcc any make

(*) In Unix the exact prefix can be configured in the configuration step (it doesn't have to be `/usr/local'); what we want to emphasize here is that in dos, all the directories coincide while in unix they can be in different locations (for example to enable multiple users or to share data in a network).


3. CONFIGURATION

After installing ManTa each user should configure it with the command:
manconf
manconf allows the user to choose: the language of the interface, a text editor (that will be used for editing ADTs, sources or displaying some information) and a compiler (that will be used to compile the generated code).

By editing the appropriate configuration files, other aspects of ManTa can be configured:

  1. The interface: it can be plain (text) or emacs (requires the text editor emacs).
  2. Directories to save and read files (ADTs, messages, printed ADTs, templates and theorems).
  3. Messages shown to the user.
  4. Labels of menus.
  5. Templates for code generation.

By default the plain interface, with standard directories, messages, labels and templates will be configured by manconf, if you want to use the emacs interface, check the instructions in the file readme.txt of the documentation directory (you can check the path of the documentation directory by running manconf).

To configure more fine details edit the appropriate configuration files. All the configuration files have a similar format: text files, where each line could have a line number followed by a space, a configuration option between dots (e.g.: ".D_ADT.") and after that commentaries (the commentaries cannot include dots).

3.1. Initialization file

The main configuration file is ~/.manta/manta.ini under Unix and manta.ini in the installation directory under Dos. The format of this file is
.<Emacs interface>. 0 if you want plain interface, 1 if you want Emacs interface
.<editor>.          Name of the text editor to use (when using plain interface). If blank the standard input will be used
.<option1>.         Command line option of the editor to go to a specific line
.<option2>.         Command line option of the editor to edit a file in read only mode
.<dir_messages>.    Directory with messages of the systems
.<dir_templates>.   Directory with templates for C code
.<dir_adts>.        Directory to save bytecode of ADT
.<dir_temp>.        Directory to save temporary files.
.<dir_print>.       Directory to save "printed" TADs (i.e textual representation)
.<unused>.         
.<dir_conj>.        Directory to save conjectures and theorems
.<dir_prot>.        Directory to save generated code
.<unused>. 
.<file_keywords>.   Name of keywords file (it must be in directory <dir_messages>)
.<file_menus>.      Name of file with menus lables (it must be in <dir_messages>)
.<file_messages>.   Name of file with messages (it must be in <dir_messages>)
.<header_func.i>.   Template for function header (must be in <dir_templates>)
.<tad.c>.           Template for selectors (must be in <dir_templates>)
.<tad.h>.           Template for headers
.<tad.mak>.         Template for makefile
.<tad_cons.inc>.    Template for constructors
.<tad_defs.h>.      Template for data declaration
.<tad_inter.c>.     Template for interface functions
.<tad_inter.h>.     Template for header of interface functions
.<tad_main.c>.      Template for the main program

3.2. Messages File

The messages file is a text file, where each line has the following format:

<number>  .<message>.

Where the number is the internal code for the message, a space  is required after the number, and dots before and after the message are also required.  The message can contain control characters like \n, \t, %d, %s (typical for printing strings with the function printf in ANSI C).

ManTa is distributed with two messages files, they are located in the directory for messages (see the previous section).

3.3. Menus File

The menus file must be a text file. Each menu has a number, a descriptive name and the options. After the number (enclosed between < and >) there must be a line specifying the amount of options, then another line and then the options. The descriptive name and the options must be enclosed with dots.  There are available two menus files (english and spanish) they are located in directory for messages.
 

3.4. Templates

The code generated in the C language can be partly configured.  The current indentation and templates follow the guidelines of  [Tor91].

In the directory for templates there are available versions of these templates in spanish and in english
 


4. THE MANTA SYSTEM


The ManTa system consists of a kernel and an interface.  The interface can be changed in accordance to your needs, now there are availabe three interfaces: command line tools, a plain (text) interface and an interface for the emacs text editor. The kernel of ManTa has three major components, that will be presented in this section along with the interfaces:

4.1. The interfaces

4.1.1 The command line tools

The command line tools can be invoked from a shell or from a Makefile --for example to process several files. They receive parameters in the command line and eventually some options. The common options to all the tools are: The usage syntax and the purpose of the available tools are:

mancomp [-i <confFile>] [-d <workDir>] <input> <output>
To check the syntax of a ManTa program <input>, and to generate the bytecode <output>.
manrew [-i <confFile>] [-d <workDir>] <input> <output>
To evaluate (i.e rewrite) the expressions of the text file <input>, and leave the results in the file <output>.
manprove [-i <confFile>] [-d <workDir>] [-p <file_proved>] [-n <file_not_proved>] <conj> [<conj> ...]
Tries to prove the conjectures in the input files. Send the proved conjectures to file_proved and the unproved conjectures to file_unproved (if the options -p or -n are not specified sends the corresponing resuts to standard output).
m2c [-i <confFile>] [-d <workDir>] [-b] <spec> [<spec> ...]
Generates code in C from the specifications that receives. If the option -b is given, it treats the input as bytecode (by default it treats the input as text files).
m2ocaml [-i <confFile>] [-d <workDir>] [-b] [-o <outDir>] <spec> [<spec> ...]
This tool could not be present in your platform (it is only available for Unix, if it was selected during the installation of the system). m2ocaml translates the ManTa specifications that receive to modules in the Ocaml language. If the option -b is given, it treats the input as bytecode (by default it treats the input as text files). If the option -o along with a directory name is given, the generated ocaml code is sent to that directory (by default it is send to the current directory).

4.1.2 The plain interface

To start the plain interface type from a shell:
manta
optionally you can pass as options:

All the interaction with this interface is done through menus.  You can choose the desired option by typing it or part of it and then pressing ENTER.  In all the menus there is an option Exit to return to the previous menu (in the case of the top menu, it will exit from the program), pressing ENTER without a word is equivalent to choose Exit.

There are many operations that require edition of texts, this edition is done with an external text editor, that must be configured as explained in section 2.
 

4.1.2 The emacs interface

Once configured, run the Emacs editor (e.g. emacs).  Press C-c m (i.e. [CTRL]+[C] and then [M]).  In the status bar should appear "Configuration file for ManTa:",  press [ENTER] and you will see the Main Menu.
 To choose an option put the cursor on it, and press [ENTER].

.

.

4.2. Types

In the ManTa interfaces and in this manual,  the concept "Abstract Data Type" is abbreviated as ADT or as type. The operations that can be done with ADTs from the interfaces are:
 
Option
Description
Directory
Shows the ADTs in disk. The usual extension for ADTs is .adt, they are in the ADTs directory specified in the initialization file. (by default D_ADT)
New
New TADs can be defined from scratch (inductive types) or with metaoperations that will be described later 

In  DOS without Long File Name support, it is recommended to use name with less than 5 characters
Edit
To browse or modify an ADT that is already loaded
Load
Allows the user to load an ADT from the ADT directory.  The file must have ManTa file format.
Save
Saves the current ADT in ManTa file format.
Prints
Saves a text representation of the file in the directory configured in the initialization file. (by default D_PRNADT)
Delete
Deletes the current ADT from memory and disk

There are two important implementation details to have in mind:

  1. All the versions of ManTa store and work with the types in one directory (usually D_ADT), and they use an special file format. This file format can be parsed efficiently and easily but it results very expensive in space, since generally each specification written in this format requires more space than the required by the plain (text) version. This feature tends to disappear in future ManTa releases, but up to ManTa 3.1 it remains.
  2. All the ADTs stored in the directory for ADTs (by default D_ADT) conform the environment.  This concept plays an important role for the semantics, since the semantics is not given to a single ADT, but to the set of all the defined ADTs,  that is  the environment.  This feature eases some operations (as the creation of extensions) but it also makes difficult the nomenclature, since there cannot be repeated names of functions in different ADTs.


New ADTs can be created from scratch, by using the ManTa language or can be created semi-automatically with  metaoperations.  A brief description of the ManTa language and of the metaoperations will be given. A complete description including semantics issues can be found in [LangSpec].

4.2.1 Overview of the ManTa language

Each  ADT  represents a set, the elements of the represented set are produced by functions and constants called generators.  For uniformity in the notation the constants are specified also as functions with empty domain.   For example the set of boolean values true and false in ManTa is represented with the ADT BOOL whose generators are the constants TRUE and FALSE, these constants as functions in ManTa are written as TRUE:->BOOL, FALSE:->BOOL.

Given one or more ADTs, it is possible to specify operations on it/them.  These operations are specified with functions called here selectors.  The selectors are intended to be functions that receive a value from a given domain and produce a value in a codomain.  In ManTa the domain can be an ADT or the cartesian product of ADTs and the codomain must be an ADT.  For example the function AND: BOOL * BOOL -> BOOL, expects two booleans and produce a third boolean.

Every ADT in ManTa has two sections: signature and axioms.  In the signature the generators and the selector of the ADT are presented, including its type (i.e. domain and codomain) and other abstract information. In the axioms section the behavior of each function is described.  The syntax of an ADT in ManTa is:

ADT name [parameter]
INITIALS
  initials
CONSTRUCTORS
  constructors
SELECTORS
  selectors
AXIOMS
  axioms

The signature is composed by the initials, the constructors and the selectors. The name of the ADT must be a string (without special characters). The parameter (a type place holder) is optional and when it appears the type is generic or parametric.

The initials are generators of the ADT whose domain doesn't contain the defined ADT (in particular constants are initials), the constructors are generators of the ADT that must include in its domain the defined ADT. For example in accordance to Peano, the natural numbers can be produced with the constant 0 and the successor function. In ManTa it is represented with the ADT NAT that has as generators the initial ZERO:->NAT and the constructor SUC:NAT->NAT

The axioms of an ADT specify the behavior of the selectors, this behavior must be specified with several restrictions, those restrictions make the description sometimes difficult, but they ensure many theoretical aspects (for example that what you write has a logical model, that you will be able to state conjectures easily, that it can be translated to several languages, and that the selectors are conservative). Each axiom must be of the form:
leftside=rightside
The leftside must be a selector instatiated with generators and variables (no repeated variables), the right side can be an expression like :

The ERROR symbol allows you, to specify where a selector is undefined, hence by this mean is possible to specify partial functions. For example the selector PRED of the natural numbers can be specified as follows:
PRED(ZERO)=ERROR
PRED(SUC(x))=x
Note that x is a variable, and ERROR was used to specify that the PRED function is undefined in ZERO.
To make its job and maintain semantical properties, the ERROR symbol can appear as the  right side of an expression or as one of the expressions in a if-then-else-fi statement.

Other requirements that the specifications must fulfill  are (checked by the system, before accepting a new ADT): everything must have type, the axioms for a selector must cover the domain, the axioms for a selector must be strongly locally confluent (this last property ensures that there are no contradictions between two axioms for the same selector).

It's a good moment to check the whole specification of the ADTs BOOL and NAT that appears in the Apendix A of this manual.

Note that those types (NAT and BOOL) as well as any other basical type, must have an equality. The name of the equality must be EQ_name where name is the name of the ADT.  A basical type is a specification with generators and without parameters; when a specification doesn't have generators, it does not represent a  set but it must have selectors that operate with existing ADTs. These specifications are called extensions and they don't need an equality, as the following example shows:

ADT ExtNAT[]
INITIALS
CONSTRUCTORS
SELECTORS
  ack: NAT(i) * NAT -> NAT
 /* Ackerman function, this shows that ManTa can express more than
    primitive recursive functions */

AXIOMS

  ack(ZERO,y)=SUC(y)
  ack(SUC(x),y)=
    if ISZERO(y) then
      ack(x,SUC(ZERO))
    else
      ack(x,ack(SUC(x),PRED(y)))
    fi

An ADT with a parameter is a generic type (also known as parametric type), these types can be instantiated, that is its parameter can be replaced with an existing type to produce a new type. By now a generic types can have at most one parameter. One example of a generic ADT can be found in the Apendix A, the classical ADT List[X].

It is also possible to write a generic extension, although with this technique by now, probably the only interesting example is:
 

ADT AddNEQ [T]
/* When this type is instantiated an extension to type T is produced. T is extended with a not-equal predicate */

INITIALS
CONSTRUCTORS
SELECTORS
  NEQ: T*T->BOOL
AXIOMS
  NEQ(x,y)=NOT(EQUAL(x,y))


As a summary the following table describes a classification of types in ManTa:
 

Name Generators Parameters Commentaries
Basic Type
Yes
Usual ADT (e.g. NAT)
Extension They only add new selectors to the system of ADTs
Generic Type
Yes
Yes
Also known as parametric types (e.g. List). 
Generic Extension
Yes
Types that generate extensions when instanced

In addition to this classification, basic ADTs can be:

4.2.2 Expressiveness of the ManTa Language

This is a difficult question since it can be viewed from several points of view.

From the computability point of view, considering  the selectors, any primitive recursive function can be expressed, but also non primitive recursive functions like the Ackerman functions can be easily written.  It is also possible to write a simulator for a Turing machine in ManTa, hence ManTa can compute any Turing-computable function.

From the set theoretic point of view, the problem of the sets that can be represented is more delicate, since in ManTa they must be produced by generators (initials and constructors), and there is no way to express restrictions on the generators.
By a moment let's avoid the equality function and let's suppose that for all ADTs it is  the syntactical equality.  In this case, finite sets can be represented, but it is mandatory to write explicitly all the elements of the set with initials (all the elements must be written as constants, or part of them can be embedded from another finite set with initials).  If there is at least one constructor the set is infinite, and its cardinality cannot be greater than w (cardinality of natural numbers).  The introduction of the equality generates equivalence classes in the represented set, and hence it cardinality decreases or remains equal.

Since it's also possible to write mutually recursive types (the generators of both ADTs depend on each other),  the expressiveness of ManTa to generate types is the same that the Caml, C, Pascal, Java or any typical programming language. However some languages give more help to write finite sets (for example in Pascal an interval can be written as a..b).  In ManTa this effect cannot be achieved although the mechanism of restriction can help in such situation.

From the logical point of view the question "What can be proved?"  is more interesting. By now the theorem prover of ManTa only has support for universally quantified equalities,  and it assumes that the variables always take defined values.
 

4.2.3. Metaoperations in ManTa to create new Types

ManTa offers the user the possibility to create new ADTs from scratch, but also offers some semi-automatically operations (in some cases completely automatically) to create them based on existing ones. These operations are described here and an example of each one is given.
 
Operation Input Output Typical Example User intervention
Instatiation A generic type and a basic type A new type obtained after instatiation of the parameter in the generic type with the basic one. Instantiate List[X] with NAT to obtain a list of natural numbers No
Copy Any type/extension A new type/extension with names changed Copy NAT as NAT2 (all the function names will be changed) No
Cartesian Product Two basical types The cartesian product of the inputs with some additional selectors NAT x NAT two obtain a TAD of pairs of Naturals No
Restriction A basical type and a restriction predicate that must be defined for all the type An extension to the type with analogous function but defined only where the predicate is TRUE NAT restricted to the predicate EvenNAT to obtain functions that operate only on Even naturals No
Direct Sum Two different basical types Union between the input types. Defines all the selectors (of both types) for the new generators
Completation A basical type and a new symbol A new type with analogous generators to the received type plus the new symbol as a new constant of the type Complete NAT with a new symbol INF to represent Infinite. Redefine all the selectors in the new constant
Variation Two basical types A new type that can be seen as the first or as the second Complex numbers in polar notation and Complex numbers in cartesian notation with a variation to yield Complex numbers. The user must give functions to translate from one representation to the other and optionally can add new operations on both.
Representation Two basical types A new extension of the second type to "codify" the functionality of the first BOOL represented with NAT (for example TRUE with ONE and FALSE with ZERO) The user must specify all the selectors of the represented type. The system generates prove obligations (see sec. )
Composition of Representations Two representations "compatible" A new representation obtained by composition BOOL represented with NAT, NAT represented with Lists of one symbol, to obtain BOOL represented with Lists of one symbol. No

The mentioned examples are now shown in more detail, however not the whole ADT is transcribed in all the cases, just some portions of each one. (You can see the whole example by using the ManTa system!)

Instatiation.  The parameter X of List is instanced with NAT to produce type ListNAT:
 

ADT ListNAT [  ]

INITIALS
nil_ListNAT :                                  -> ListNAT

CONSTRUCTORS
cons_ListNAT: NAT * ListNAT                    -> ListNAT

SELECTORS
head_ListNAT   : ListNAT(i)                       -> NAT
tail_ListNAT   : ListNAT(i)                       -> ListNAT
length_ListNAT   : ListNAT(i)                       -> NAT
concat_ListNAT   : ListNAT(i) * ListNAT             -> ListNAT
memberList_ListNAT   : ListNAT(i) * NAT                 -> BOOL
isEmptyList_ListNAT   : ListNAT(i)                       -> BOOL
EQ_ListNAT(c): ListNAT(i) * ListNAT(i)          -> BOOL

AXIOMS
 

head_ListNAT(nil_ListNAT) = ERROR
head_ListNAT(cons_ListNAT(X1,L2)) = X1

...

memberList_ListNAT(nil_ListNAT,X1) = FALSE
memberList_ListNAT(cons_ListNAT(X1,L2),X3) = if EQ_NAT(X1,X3)
                                                  then TRUE
                                                  else
                                                    memberList_ListNAT(L2,X3)
                                                  fi
...
 


Copy.  The ADT NAT has been copied in NAT2
 

ADT NAT2 [  ]

INITIALS
ZERO_NAT2   :                                  -> NAT2

CONSTRUCTORS
SUC_NAT2    : NAT2                             -> NAT2

SELECTORS
ADD_NAT2    : NAT2 * NAT2(i)                   -> NAT2
ISZERO_NAT2   : NAT2(i)                          -> BOOL
...

AXIOMS

ADD_NAT2(N1,ZERO_NAT2) = N1
ADD_NAT2(N1,SUC_NAT2(N2)) = SUC_NAT2(ADD_NAT2(N1,N2))

ISZERO_NAT2(ZERO_NAT2) = TRUE
ISZERO_NAT2(SUC_NAT2(N1)) = FALSE

...


Cartesian Product. Pair of naturals
 

ADT Pair [  ]
/*  =  NAT x NAT */

INITIALS
PAIR_Pair   : NAT * NAT                        -> Pair

CONSTRUCTORS

SELECTORS
PROY_Pair1   : Pair(i)                          -> NAT
PROY_Pair2   : Pair(i)                          -> NAT
SUC1        : Pair                             -> Pair
ADD_Pair1   : Pair * Pair(i)                   -> Pair
...
SUC2        : Pair                             -> Pair
ADD_Pair2   : Pair * Pair(i)                   -> Pair
ISZERO_Pair2   : Pair(i)                          -> BOOL
...

AXIOMS

PROY_Pair1(PAIR_Pair(N1,N2)) = N1

PROY_Pair2(PAIR_Pair(N1,N2)) = N2

SUC1(P1) = PAIR_Pair(SUC(PROY_Pair1(P1)),PROY_Pair2(P1))

ADD_Pair1(P1,P2) = PAIR_Pair(ADD(PROY_Pair1(P1),PROY_Pair1(P2)),PROY_Pair2(P1))

Restriction. The ADT NAT restricted to the predicate EvenNAT:NAT->BOOL given by

ADT ENAT [  ]
/*  =  ( NAT : EvenNAT )*/

INITIALS

CONSTRUCTORS

SELECTORS
EvenNAT  (c): NAT(i)                           -> BOOL
ADD_ENAT    : NAT * NAT                        -> NAT
ISZERO_ENAT   : NAT                              -> BOOL
...

AXIOMS

EvenNAT(ZERO) = TRUE
EvenNAT(SUC(N2)) = NOT(EvenNAT(N2))

ADD_ENAT(X1,X2) = if AND(EvenNAT(X1),EvenNAT(X2))
                       then ADD(X1,X2)
                       else ERROR
                  fi

ISZERO_ENAT(X1) = if EvenNAT(X1)
                       then ISZERO(X1)
                       else ERROR
                  fi
...
 


Direct Sum.

Completation. A possible completion of NAT with a symbol for infinite i.e INF.
 

ADT INAT [  ]
/*  =  NAT + { INF }*/

INITIALS
ZERO_INAT   :                                  -> INAT
INF         :                                  -> INAT

CONSTRUCTORS
SUC_INAT    : INAT                             -> INAT

SELECTORS
ADD_INAT    : INAT * INAT(i)                   -> INAT
ISZERO_INAT   : INAT(i)                          -> BOOL
...

AXIOMS
ADD_INAT(N1,ZERO_INAT) = N1
ADD_INAT(N1,SUC_INAT(N2)) = SUC_INAT(ADD_INAT(N1,N2))
ADD_INAT(N1,INF) = INF

ISZERO_INAT(ZERO_INAT) = TRUE
ISZERO_INAT(SUC_INAT(N1)) = FALSE
ISZERO_INAT(INF) = FALSE
...
 


Variation. The ADT ComplexPol (complex in polar representation) along with the ADT ComplexCart (complex in cartesian representation) can be viewed as one, via the variation Complex
 

ADT Complex [  ]
/*  =  ComplexPol U ComplexCar */

INITIALS
Complex_ComplexPol: ComplexPol                       -> Complex
Complex_ComplexCar: ComplexCar                       -> Complex

CONSTRUCTORS

SELECTORS
ComplexPol_ComplexCar   : ComplexPol(i)                    -> ComplexCar
ComplexCar_ComplexPol   : ComplexCar(i)                    -> ComplexPol
EQ_Complex(c): Complex(i) * Complex(i)          -> BOOL

AXIOMS

...

EQ_Complex(Complex_ComplexPol(C1),Complex_ComplexPol(C2)) = EQ_ComplexPol(C1,C2)
EQ_Complex(Complex_ComplexPol(C1),Complex_ComplexCar(C2)) = EQ_ComplexCar(ComplexPol_ComplexCar(C1),C2)
EQ_Complex(Complex_ComplexCar(C1),Complex_ComplexPol(C2)) = EQ_ComplexCar(C1,ComplexPol_ComplexCar(C2))
EQ_Complex(Complex_ComplexCar(C1),Complex_ComplexCar(C2)) = EQ_ComplexCar(C1,C2)


Representation. BOOL represented with NAT in an extension called BOOLN
 

ADT BOOLN [  ]
/*  BOOLN : BOOL -> NAT */

INITIALS

CONSTRUCTORS

SELECTORS
BOOLN_TRUE   :                                  -> NAT
BOOLN_FALSE   :                                  -> NAT
BOOLN_AND   : NAT * NAT                        -> NAT
BOOLN_OR    : NAT * NAT                        -> NAT
BOOLN_NOT   : NAT                              -> NAT
BOOLN_IMP   : NAT * NAT                        -> NAT
BOOLN_EQ_BOOL   : NAT * NAT                        -> BOOL

AXIOMS

BOOLN_TRUE = SUC(ZERO)
BOOLN_FALSE = ZERO
BOOLN_AND(N1,N2) = MULT(N1,N2)
BOOLN_OR(N1,N2) = MIN(ADD(N1,N2),SUC(ZERO))
BOOLN_NOT(N1) = MOD(SUC(N1),SUC(SUC(ZERO)))
BOOLN_IMP(N1,N2) = BOOLN_OR(BOOLN_NOT(N1),N2)
BOOLN_EQ_BOOL(N1,N2) = EQ_NAT(N1,N2)


The given representation can be proved to be correct. i.e that all the valid axioms of selectors in BOOL are still valid.  All the axioms are valid, however with the automatic theorem prover of ManTa,  13 of the 14 axioms can be demostrated.

Another representation will be given , here NAT will be represented with a List of Boolean (called here lb). The resulting representation is called nlb

ADT nlb [  ]

INITIALS

CONSTRUCTORS

SELECTORS
nlb_ZERO    :                                  -> lb
nlb_SUC     : lb                               -> lb
nlb_ADD     : lb * lb                          -> lb
nlb_ISZERO   : lb(i)                               -> BOOL
nlb_MULT    : lb(i) * lb                          -> lb
nlb_PRED    : lb                               -> lb
nlb_MAX     : lb * lb                          -> lb
nlb_MIN     : lb * lb                          -> lb
nlb_GT      : lb * lb                          -> BOOL
nlb_LT      : lb * lb                          -> BOOL
nlb_GE      : lb * lb                          -> BOOL
nlb_LE      : lb * lb                          -> BOOL
nlb_FACT    : lb(i)                            -> lb
nlb_EXP     : lb * lb (i)                         -> lb
nlb_EVEN    : lb                               -> BOOL
nlb_ODD     : lb                               -> BOOL
nlb_DIV     : lb * lb                          -> lb
nlb_MOD     : lb * lb                          -> lb
nlb_DIVIDES   : lb * lb                          -> BOOL
nlb_SUBS    : lb * lb                          -> lb
nlb_EQ_NAT   : lb * lb                          -> BOOL

AXIOMS

nlb_ZERO=nil_lb
nlb_SUC(L1)=cons_lb(TRUE,L1)
nlb_ADD(L1,L2)=concat_lb(L1,L2)
nlb_ISZERO(nil_lb)=TRUE
nlb_ISZERO(cons_lb(L1,P1))=FALSE
nlb_MULT(nil_lb,L2)=nil_lb
nlb_MULT(cons_lb(P1,L1),L2)=nlb_ADD(nlb_MULT(L1,L2),L2)
nlb_PRED(L1)=tail_lb(L1)
nlb_MAX(L1,L2)=if GT(length_lb(L1),length_lb(L2)) then L1 else L2 fi
nlb_MIN(L1,L2)=if LT(length_lb(L1),length_lb(L2)) then L1 else L2 fi
nlb_GT(L1,L2)=GT(length_lb(L1),length_lb(L2))
nlb_LT(L1,L2)=LT(length_lb(L1),length_lb(L2))
nlb_GE(L1,L2)=GE(length_lb(L1),length_lb(L2))
nlb_LE(L1,L2)=LE(length_lb(L1),length_lb(L2))
nlb_FACT(nil_lb)=cons_lb(TRUE,nil_lb)
nlb_FACT(cons_lb(P1,L1))=nlb_MULT(cons_lb(P1,L1),nlb_FACT(L1))
nlb_EXP(L1,nil_lb) = nlb_SUC(nil_lb)
nlb_EXP(L1,cons_lb(P3,L2)) = nlb_MULT(nlb_EXP(L1,L2),L1)
nlb_EVEN(L1)= EVEN(length_lb(L1))
nlb_ODD(L1)=ODD(length_lb(L1))
nlb_DIV(N1,N2) = if nlb_ISZERO(N2)
                  then ERROR
                  else if nlb_GE(N1,N2)
                      then nlb_SUC(nlb_DIV(nlb_SUBS(N1,N2),N2))
                      else nlb_ZERO
                 fi
             fi
nlb_MOD(N1,N2) = if nlb_ISZERO(N2)
                  then ERROR
                  else if nlb_GE(N1,N2)
                      then nlb_MOD(nlb_SUBS(N1,N2),N2)
                      else N1
                 fi
             fi
nlb_DIVIDES(L1,L2)=nlb_ISZERO(nlb_MOD(L1,L2))
nlb_SUBS(N1,nil_lb) = N1
nlb_SUBS(N1,cons_lb(P3,N2)) = nlb_PRED(nlb_SUBS(N1,N2))
nlb_EQ_NAT(L1,L2)=EQ_NAT(length_lb(L1),length_lb(L2))


For this case of the 45 axioms in the ADT NAT, 40 can be proved by the ManTa theorem prover. One of the unproved conjectures shows a real problem (that in this example we will ignore):
 

nlb_PRED(nlb_ZERO) = nlb_ZERO
This conjecture is proposed since PRED(ZERO)=ZERO in the NAT specification, but after rewriting this expression it becomes
tail_lb(nil_lb)=nil_lb
and the definition for List (and hence lb) for tail is:
tail(nil)=ERROR
that in fact contradicts the conjecture

Composition of representations.  With the two previous examples a third representation can be obtained automatically via composition. The new representation is BOOL represented with a List of BOOL , that here we call blb.

ADT blb [  ]
/*  blb : BOOL -> lb */

INITIALS

CONSTRUCTORS

SELECTORS
blb_TRUE    :                                  -> lb
blb_FALSE   :                                  -> lb
blb_AND     : lb * lb                          -> lb
blb_OR      : lb * lb                          -> lb
blb_NOT     : lb                               -> lb
blb_IMP     : lb * lb                          -> lb
blb_EQ_BOOL   : lb * lb                          -> BOOL

AXIOMS

blb_TRUE = nlb_SUC(nlb_ZERO)
blb_FALSE = nlb_ZERO

blb_AND(N1,N2) = nlb_MULT(N1,N2)

blb_OR(N1,N2) = if LT(length_lb(concat_lb(N1,N2)),length_lb(nlb_SUC(nlb_ZERO)))
                     then nlb_ADD(N1,N2)
                     else nlb_SUC(nlb_ZERO)
                fi
blb_NOT(N1) = if nlb_ISZERO(nlb_SUC(nlb_SUC(nlb_ZERO)))
                   then ERROR
                   else if nlb_GE(nlb_SUC(N1),nlb_SUC(nlb_SUC(nlb_ZERO)))
                       then nlb_MOD(nlb_SUBS(nlb_SUC(N1),nlb_SUC(nlb_SUC(nlb_ZE$                       else nlb_SUC(N1)
                  fi
              fi

blb_IMP(N1,N 2) = blb_OR(blb_NOT(N1),N2)

blb_EQ_BOOL(N1,N2) = EQ_NAT(length_lb(N1),length_lb(N2))


 
 

4.3. The theorem prover and the rewriting motor


The operations that can be done with the interfaces are:
 

Opción
Descripción
Directory
Shows the conjectures and theorems available to browse.  These are located in the directory specified in the initialization file (by default D_THEO)
Normalization
Evaluates a list of expressions with the rewriting motor.
Conjectures
Tries to prove a list of conjectures with the theorem prover.
Proved
To browse and edit proved conjectures
Not_Proved
To browse and edit not proved conjectures
Save_Proved
To save a successful proofs.
Save_Not_Proved 
To save a failed proof..

4.3.1 The rewriting Motor of ManTa

The operational semantics of ManTa is described with a rewriting system in [LangSpec].  This rewriting system was implemented and is part of the ManTa system.  It's main purpose is to evaluate expressions. An expression can include any of the functions defined in the existing ADTs, variables, the if-then-else-fi construction and the EQUAL function.

Although the ERROR symbol could be used inside an expression  that is intended to be rewritten, it is not meaningful for the rewriting motor,  since ERROR  is used only to express where a function is undefined (that is in the axioms of an ADT).  When an evaluation includes the ERROR symbol the result is undefined (the only exception is  if-then-else-fi that can have one of its second or third expressions undefined an however it can be defined).   In terms of programming languages the apparition of ERROR is like an exception or a failed assertion. (Since a function was evaluated in a point of its domain where it was undefined).

With regard to the EQUAL function, it will be rewritten to a  EQ_TAD function in accordance to the type.  Note that this makes sense since every ADT must have an equality function (the exceptions are extensions, but as it was already discussed these are not ADTs).s

The evaluations of the rewriting Motor always use the axioms given by the user in all the defined ADTs and the following rules:

if TRUE  then E1 else E2 fi -> E1
if FALSE then E1 else E2 fi -> E2

Below, some examples will be given. These examples use the axioms of the ADTs NAT, BOOL and List given in the Appendix A:

FACT(SUC(SUC(SUC(ZERO)))) = SUC(SUC(SUC(SUC(SUC(SUC(ZERO))))))
LT(EXP(SUC(SUC(ZERO)),SUC(SUC(ZERO))),FACT(SUC(SUC(ZERO)))) = FALSE
length(cons(x,nil)) = SUC(ZERO)

Note that in the last example length is applied to a variable x.  This cannot be done in many programming languages, and it is possible due to the rewriting motor:
MAX(SUC(SUC(X)),SUC(SUC(SUC(X)))) = SUC(SUC(MAX(X,SUC(X))))
MULT(SUC(ZERO),x) = x
 

4.3.2 The theorem prover of ManTa

The ManTa kernel includes a theorem prover, that can handle universally quantified equalities.  For example ManTa can prove the conmutativity of the addition. i.e for all x,y natural number x+y=y+x in ManTa becomes:
ADD(X,Y)=ADD(Y,X)
This property although trivial for the user is not trivial for ManTa, since the definition of the function ADD in the ADT NAT doesn't involve explicitly conmutativity:

  ADD(N1,ZERO) = N1
  ADD(N1,SUC(N2)) = SUC(ADD(N1,N2))

The current theorem prover has to make induction twice in order to prove this.  The proof that it gives is:
 

  Beginning of induction

  Base case
  Substitution: X -> ZERO
      ADD(ZERO,Y) = ADD(Y,ZERO)

      Rule to left side: ADD(ZERO,X) = X
      Rule to right side: ADD(N1,ZERO) = N1
      Y = Y

  Base case proof successful

  Induction step
  Induction hypothesis : ADD(_X,Y) = ADD(Y,_X)
  Substitution: X -> SUC(_X)
      ADD(SUC(_X),Y) = ADD(Y,SUC(_X))

      Rule to right side: ADD(N1,SUC(N2)) = SUC(ADD(N1,N2))
      ADD(SUC(_X),Y) = SUC(ADD(Y,_X))

    Beginning of induction

    Base case
    Substitution: Y -> ZERO
        ADD(SUC(_X),ZERO) = SUC(ADD(ZERO,_X))

        Rule to left side: ADD(N1,ZERO) = N1
        Rule to right side: ADD(ZERO,X) = X
        SUC(_X) = SUC(_X)

    Base case proof successful

    Induction step
    Induction hypothesis : ADD(SUC(_X),_Y) = SUC(ADD(_Y,_X))
    Substitution: Y -> SUC(_Y)
        ADD(SUC(_X),SUC(_Y)) = SUC(ADD(SUC(_Y),_X))

        Rule to left side: ADD(N1,SUC(N2)) = SUC(ADD(N1,N2))
        SUC(ADD(SUC(_X),_Y)) = SUC(ADD(SUC(_Y),_X))

        Rule to left side: ADD(SUC(_X),_Y) = SUC(ADD(_Y,_X))
        SUC(SUC(ADD(_Y,_X))) = SUC(ADD(SUC(_Y),_X))

      Semantic proof
          EQ_NAT(SUC(SUC(ADD(_Y,_X))),SUC(ADD(SUC(_Y),_X))) = TRUE

          Rule to left side: EQ_NAT(SUC(N1),SUC(N2)) = EQ_NAT(N1,N2)
          EQ_NAT(SUC(ADD(_Y,_X)),ADD(SUC(_Y),_X)) = TRUE

      Semantic proof failed
    Induction step proof failed

    Induction step
    Induction hypothesis : SUC(ADD(_Y,_X)) = ADD(SUC(_X),_Y)
    Substitution: Y -> SUC(_Y)
        ADD(SUC(_X),SUC(_Y)) = SUC(ADD(SUC(_Y),_X))

        Rule to left side: ADD(N1,SUC(N2)) = SUC(ADD(N1,N2))
        SUC(ADD(SUC(_X),_Y)) = SUC(ADD(SUC(_Y),_X))

      Semantic proof
          EQ_NAT(SUC(ADD(SUC(_X),_Y)),SUC(ADD(SUC(_Y),_X))) = TRUE

          Rule to left side: EQ_NAT(SUC(N1),SUC(N2)) = EQ_NAT(N1,N2)
          EQ_NAT(ADD(SUC(_X),_Y),ADD(SUC(_Y),_X)) = TRUE

      Semantic proof failed
    Induction step proof failed

    End of induction

  Induction step proof failed

  Induction step
  Induction hypothesis : ADD(Y,_X) = ADD(_X,Y)
  Substitution: X -> SUC(_X)
      ADD(SUC(_X),Y) = ADD(Y,SUC(_X))

      Rule to right side: ADD(N1,SUC(N2)) = SUC(ADD(N1,N2))
      ADD(SUC(_X),Y) = SUC(ADD(Y,_X))

      Rule to right side: ADD(Y,_X) = ADD(_X,Y)
      ADD(SUC(_X),Y) = SUC(ADD(_X,Y))

    Beginning of induction

    Base case
    Substitution: Y -> ZERO
        ADD(SUC(_X),ZERO) = SUC(ADD(_X,ZERO))

        Rule to left side: ADD(N1,ZERO) = N1
        Rule to right side: ADD(N1,ZERO) = N1
        SUC(_X) = SUC(_X)

    Base case proof successful

    Induction step
    Induction hypothesis : ADD(SUC(_X),_Y) = SUC(ADD(_X,_Y))
    Substitution: Y -> SUC(_Y)
        ADD(SUC(_X),SUC(_Y)) = SUC(ADD(_X,SUC(_Y)))

        Rule to left side: ADD(N1,SUC(N2)) = SUC(ADD(N1,N2))
        Rule to right side: ADD(N1,SUC(N2)) = SUC(ADD(N1,N2))
        SUC(ADD(SUC(_X),_Y)) = SUC(SUC(ADD(_X,_Y)))

        Rule to left side: ADD(SUC(_X),_Y) = SUC(ADD(_X,_Y))
        SUC(SUC(ADD(_X,_Y))) = SUC(SUC(ADD(_X,_Y)))

    Induction step proof successful

    End of induction

  Induction step proof successful

  End of induction

Successful proof

To prove a conjecture ManTa tries several techniques:
  1. Rewriting: Both sides of the equation are rewritten to their normal forms. If the normal forms are equal the conjecture is proved
  2. Induction: If the normal forms of each side of the equalitiy have appropriate variables to make induction, an induction proof is tried with this variable varying on the generators of the appropriate ADT.
  3. Semantical Proof: If rewriting and induction fail, it tries to apply the congruence defined by the equality and instead of proving syntactical equality: left=right tries EQUAL(left,right)=TRUE
  4. In some cases there are other attempts of proofs (cases and generalization) but they are, by now, not very useful.


The current theorem prover of ManTa is not very powerful (6.3% of proof capacity in NQTHM92 benchmark), there are other inductive theorem provers that give better results, however this tool is useful for some rutinary and simple proofs.  Before blaming the theorem prover when it cannot complete a proof, note that it is not possible to make an automatic theorem prover for interesting theories (like NAT), since determining the validity of a theorem in such a theory is an indecidible problem. Writing a theorem prover is hard, in the moment of this writing the best theorems provers can not prove the correctness of a sort algorithm neither many other "simple" algorithms.

Developing software with ManTa is not difficult, it is more difficult to decide what to prove. Usually the modeled ADTs have very interesting properties that are not evident.  For example the function concat in the  ADT List is not conmutative, but it is associative.  The proof requires induction and can be done in ManTa (i.e concat(concat(x,y),z)=concat(x,concat(y,z)) ).
To check what to prove, one way  is trying to see algebraic properties of an ADT (for example conmutativity, associativity, identity, etc.) and prove or refute them. Another way is  checking simple properties that a correct implementation of a selector must have.  For example in the case of concat and length one property that they must have is:

length(concat(x,y))=length(x)+length(y)
Fortunately, this also can be proved by ManTa after several induction attempts.  Decide what to prove is not easy it requires skills, however testing a program also requires skills, and in some ways the theorem prover of ManTa replaces many test cases of a concrete program. (For example in the implementation of the ADT List in C, testing the given property requires a lot of effort).
 

4.4. Code generation

The kernel of ManTa has a C code generator integrated.  This generator algon with an ADT can generate a test program.  The operations to use that can be done from the interfaces are:
Opción
Descripción
Directory
Shows the ADTs generated by the system
Automatic
Generates automatically the current ADT or part of it, the possibilities are:
  • Generate only Constructors
  • Generate only Selectors
  • Generate only Headers
  • Generate test program and its interface
  • Generate all of the above and makefile
Manual
It generates templates that must be filled by the user
Compile
Generates the makefile and executes it.  Note that you must configure properly the template of the makefile in accordance to your platform.
Edit
Allows the user to edit the generated code.
Execute
Runs the test program generated for an ADT

All the files that can be generated for an ADT X are:

The test program  allows the user to create and operate with expressions or "objects".  Those objects have a type and are identified (in the test program) with a name. To see the relation of those expression and the original concept of ADT, each expression corresponds to an element of the set modeled with the ADT.

In the test program, the main operations that can be done with the set of expressions are: (1) Saving (2) Loading (3) Deleting.  In addition the selectors can be applied to existing expressions to produce new expressions.
 
 
 


APPENDIX A.  Examples of ADT

A.1. ADT BOOL

ADT BOOL [  ]

INITIALS
  TRUE        :                                  -> BOOL
  FALSE       :                                  -> BOOL

CONSTRUCTORS

SELECTORS
  AND      (c): BOOL * BOOL(i)                   -> BOOL
  OR       (c): BOOL * BOOL(i)                   -> BOOL
  NOT      (c): BOOL(i)                          -> BOOL
  IMP      (c): BOOL(i) * BOOL(i)                -> BOOL
  EQ_BOOL  (c): BOOL(i) * BOOL(i)                -> BOOL

AXIOMS

  AND(B1,TRUE) = B1
  AND(B1,FALSE) = FALSE

  OR(B1,TRUE) = TRUE
  OR(B1,FALSE) = B1

  NOT(TRUE) = FALSE
  NOT(FALSE) = TRUE

  IMP(TRUE,TRUE) = TRUE
  IMP(TRUE,FALSE) = FALSE
  IMP(FALSE,TRUE) = TRUE
  IMP(FALSE,FALSE) = TRUE

  EQ_BOOL(TRUE,TRUE) = TRUE
  EQ_BOOL(TRUE,FALSE) = FALSE
  EQ_BOOL(FALSE,TRUE) = FALSE
  EQ_BOOL(FALSE,FALSE) = TRUE

A.2. ADT NAT

ADT NAT [  ]

INITIALS
  ZERO        :                                  -> NAT

CONSTRUCTORS
  SUC         : NAT                              -> NAT

SELECTORS
  ADD         : NAT * NAT(i)                     -> NAT
  ISZERO      : NAT(i)                           -> BOOL
  MULT        : NAT(i) * NAT                     -> NAT
  PRED        : NAT(i)                           -> NAT
  MAX         : NAT(i) * NAT(i)                  -> NAT
  MIN         : NAT(i) * NAT(i)                  -> NAT
  GT          : NAT(i) * NAT(i)                  -> BOOL
  LT          : NAT(i) * NAT(i)                  -> BOOL
  GE          : NAT * NAT                        -> BOOL
  LE          : NAT * NAT                        -> BOOL
  FACT        : NAT(i)                           -> NAT
  EXP         : NAT * NAT(i)                     -> NAT
  EVEN        : NAT(i)                           -> BOOL
  ODD         : NAT(i)                           -> BOOL
  DIV         : NAT * NAT                        -> NAT
  MOD         : NAT * NAT                        -> NAT
  DIVIDES     : NAT * NAT                        -> BOOL
  SUBS        : NAT * NAT(i)                     -> NAT
  EQ_NAT   (c): NAT(i) * NAT(i)                  -> BOOL

AXIOMS

  ADD(N1,ZERO) = N1
  ADD(N1,SUC(N2)) = SUC(ADD(N1,N2))

  ISZERO(ZERO) = TRUE
  ISZERO(SUC(N1)) = FALSE

  MULT(ZERO,N1) = ZERO
  MULT(SUC(N1),N2) = ADD(MULT(N1,N2),N2)

  PRED(ZERO) = ZERO
  PRED(SUC(N1)) = N1

  MAX(ZERO,ZERO) = ZERO
  MAX(ZERO,SUC(N1)) = SUC(N1)
  MAX(SUC(N1),ZERO) = SUC(N1)
  MAX(SUC(N1),SUC(N2)) = SUC(MAX(N1,N2))

  MIN(ZERO,ZERO) = ZERO
  MIN(ZERO,SUC(N1)) = ZERO
  MIN(SUC(N1),ZERO) = ZERO
  MIN(SUC(N1),SUC(N2)) = SUC(MIN(N1,N2))

  GT(ZERO,ZERO) = FALSE
  GT(ZERO,SUC(N1)) = FALSE
  GT(SUC(N1),ZERO) = TRUE
  GT(SUC(N1),SUC(N2)) = GT(N1,N2)

  LT(ZERO,ZERO) = FALSE
  LT(ZERO,SUC(N1)) = TRUE
  LT(SUC(N1),ZERO) = FALSE
  LT(SUC(N1),SUC(N2)) = LT(N1,N2)

  GE(N1,N2) = OR(EQ_NAT(N1,N2),GT(N1,N2))

  LE(N1,N2) = OR(EQ_NAT(N1,N2),LT(N1,N2))

  FACT(ZERO) = SUC(ZERO)
  FACT(SUC(N1)) = MULT(SUC(N1),FACT(N1))

  EXP(N1,ZERO) = SUC(ZERO)
  EXP(N1,SUC(N2)) = MULT(EXP(N1,N2),N1)

  EVEN(ZERO) = TRUE
  EVEN(SUC(ZERO)) = FALSE
  EVEN(SUC(SUC(N1))) = EVEN(N1)

  ODD(ZERO) = FALSE
  ODD(SUC(ZERO)) = TRUE
  ODD(SUC(SUC(N1))) = ODD(N1)

  DIV(N1,N2) = if ISZERO(N2)
                  then ERROR
                  else if GE(N1,N2)
                      then SUC(DIV(SUBS(N1,N2),N2))
                      else ZERO
                 fi
             fi

  MOD(N1,N2) = if ISZERO(N2)
                  then ERROR
                  else if GE(N1,N2)
                      then MOD(SUBS(N1,N2),N2)
                      else N1
                 fi
             fi

  DIVIDES(N1,N2) = ISZERO(MOD(N2,N1))

  SUBS(N1,ZERO) = N1
  SUBS(N1,SUC(N2)) = PRED(SUBS(N1,N2))

  EQ_NAT(ZERO,ZERO) = TRUE
  EQ_NAT(ZERO,SUC(N1)) = FALSE
  EQ_NAT(SUC(N1),ZERO) = FALSE
  EQ_NAT(SUC(N1),SUC(N2)) = EQ_NAT(N1,N2)
 

A.2. ADT List[X]

ADT List [ X ]

INITIALS
nil         :                                  -> List

CONSTRUCTORS
cons        : X * List                         -> List

SELECTORS
head        : List(i)                          -> X
tail        : List(i)                          -> List
length      : List(i)                          -> NAT
concat      : List(i) * List                   -> List
memberList   : List(i) * X                      -> BOOL
isEmptyList   : List(i)                          -> BOOL
EQ_List  (c): List(i) * List(i)                -> BOOL

AXIOMS

head(nil) = ERROR
head(cons(X1,L2)) = X1

tail(nil) = ERROR
tail(cons(X1,L2)) = L2

length(nil) = ZERO
length(cons(X1,L2)) = SUC(length(L2))

concat(nil,L1) = L1
concat(cons(X1,L2),L3) = cons(X1,concat(L2,L3))

memberList(nil,X1) = FALSE
memberList(cons(X1,L2),X3) = if EQUAL(X1,X3)
                                  then TRUE
                                  else memberList(L2,X3)
                             fi

isEmptyList(nil) = TRUE
isEmptyList(cons(X1,L2)) = FALSE

EQ_List(nil,nil) = TRUE
EQ_List(nil,cons(X1,L2)) = FALSE
EQ_List(cons(X1,L2),nil) = FALSE
EQ_List(cons(X1,L2),cons(X3,L4)) = AND(EQUAL(X1,X3),EQ_List(L2,L4))



Last update: 2/Jul/2001