 
 
 
 
 
 
 
  
The purpose of this chapter is fourfold:
The constructors of LUTINS are fixed, but you can define quasi-constructors which effectively serve as additional constructors. Quasi-constructors are desirable for several reasons:
Quasi-constructors are implemented as ``macro/abbreviations.''  For
example, the quasi-constructor quasi-equals10.1 is defined by the following
biconditional:
 
When the preparsed string representation of an expression (``preparsed
string'' for short) of the form 
 is parsed,
is parsed,  is treated as a macro with the list of arguments E1,E2: an
internal representation of the expression (``internal expression'') is
built from the preparsed string as if it had the form
is treated as a macro with the list of arguments E1,E2: an
internal representation of the expression (``internal expression'') is
built from the preparsed string as if it had the form 
 .
When an internal expression of
the form
.
When an internal expression of
the form 
 is
printed,
is
printed,  is used as an abbreviation: the printed string
representation of the expression (``printed string'') is generated
from the internal expression as if the latter had the form
is used as an abbreviation: the printed string
representation of the expression (``printed string'') is generated
from the internal expression as if the latter had the form 
 .
In other words, in string representation of the expression
looks like
.
In other words, in string representation of the expression
looks like 
 ,
an operator applied to a list of two
arguments, but it is actually represented internally as
,
an operator applied to a list of two
arguments, but it is actually represented internally as 
 .
.
Abstractly, a quasi-constructor definition consists of three components: a name, a list of schema variables, and a schema. In our example above, quasi-equals is the name, E1,E2 is the list of schema variables, and the right-hand side of the biconditional above is the schema. A quasi-constructor is defined by a user with the def-quasi-constructor form. The list of schema variables and the schema are represented together by a lambda-expression which is specified by a string and a name of a language or theory. The variables of the lambda-expression represent the list of schema variables, and the body of the lambda-expression represents the schema.
For instance, quasi-equals could be defined by:
   (def-quasi-constructor QEQUALS
     "lambda(e1,e2:ind, #(e1) or #(e2) implies e1 = e2)"
     (language the-kernel-theory))
The name of the quasi-constructor is qequals, and the
lambda-expression is the expression specified by the string in
the-kernel-theory.  After this form has been evaluated, an
expression of the form 
 is well-formed in any
language containing the language of the-kernel-theory,
provided A and B are well-formed expressions of the same type of
kind
is well-formed in any
language containing the language of the-kernel-theory,
provided A and B are well-formed expressions of the same type of
kind  .
Separate from the definition, special syntax may be
defined for parsing and printing qequals (e.g., as the infix
symbol
.
Separate from the definition, special syntax may be
defined for parsing and printing qequals (e.g., as the infix
symbol  ).
).
The quasi-constructor quasi-equals is not actually defined using
a def-quasi-constructor form in  IMPS.  It is one of a small number of
``system quasi-constructors'' which have been directly defined by the
 IMPS implementors.  A system quasi-constructor cannot be defined
using the def-quasi-constructor form because the schema of
the quasi-constructor cannot be fully represented as a  LUTINS
lambda-expression.  This is usually because one or more variables of
the schema variables ranges over function expressions of variable
arity or over expressions of both kind  and
and  .
For
example,
.
For
example, 
 is not well-defined if A and B are
of kind
is not well-defined if A and B are
of kind  ,
but
,
but 
 is well-defined as long
as A and B have the same type (regardless of its kind).  The major
system quasi-constructors are listed in Table 10.1.
is well-defined as long
as A and B have the same type (regardless of its kind).  The major
system quasi-constructors are listed in Table 10.1.
| 
 
 | 
There are two modes for reasoning with a quasi-constructor Q. In the enabled mode the internal structure of Q is ignored. For example, in this mode, when an expression Q(E1,..,En) is simplified, only the parts of the internal expression corresponding to the arguments E1,..,En are simplified, and the part corresponding to Q is ``skipped.'' Similarly, when a macete is applied to an expression Q(E1,..,En), subexpressions located in the part of the internal expression corresponding to Q are ignored. In this mode, quasi-constructors are intended to behave as if they were ordinary constructors.
In the disabled mode, the internal structure of Q has no special status. That is, deduction is performed on internal expressions as if Q was never defined. (However, in this mode expressions involving Q will still be printed using Q as an abbreviation.) The mode is activated by ``disabling Q,'' and it inactivated by ``enabling Q.'' The disabled mode is used for proving basic properties about Q. Once a good set of basic properties are proven and formalized as theorems, there is usually little need for the disabled mode. Most quasi-constructors are intended to be employed in multiple theories. Hence, you will usually want to install a theorem about a quasi-constructor with the usage transportable-macete.
For a few of the interactive proof commands, there is a dual command with the word ``insistent'' put somewhere into the command's name. For example, the dual of simplify is the simplify-insistently. Calling the dual of a command C is equivalent to disabling all quasi-constructors and then calling Citself. In other words, the dual commands behave as if there were no quasi-constructors at all. These ``insistent'' commands are intended to be used sparingly because they can disturb the internal structure corresponding to a quasi-constructor, creating a new internal expression that can no longer be abbreviated by the quasi-constructor. In visual terms, the quasi-constructor ``explodes.''
One of the advantages of working in a logic like LUTINS, with a rich structure of functions, is that generic objects like sets and sequences can be represented directly in the logic as certain kinds of functions. For instance, sets are represented in IMPS as indicators, which are similar to characteristic functions, except that x is a ``member'' of an indicator f iff f(x) is defined. Operators on indicators and other functions representing generic objects are formalized in IMPS as quasi-constructors, and theorems about these operators are proved in ``generic theories'' that contain neither constants nor axioms (except for possibly the axioms of the theory h-o-real-arithmetic). Consequently, reasoning is performed in generic theories using only the purely logical apparatus of LUTINS (and possibly h-o-real-arithmetic). Moreover, theorems about generic objects are easy to apply in other theories since the operators, as quasi-constructors, are polymorphic and since the theory interpretations involved usually have no obligations to check.
   (view-expr
     "1/0==?zz"
     (language-name h-o-real-arithmetic)
     no-quasi-constructors)
is evaluated, the expression 
 is printed as
is printed as
(#(1/0) or #(?zz)) implies 1/0=?zz.
q{e1,...,en}, where q is
a quasi-constructor, is parsed exactly like q(e1,...,en).  In
addition, the internal expression is always printed like
q{e1,...,en}, unless you have defined a special print syntax
for q.
 -equivalent).  For
example, consider the preparsed string S1
-equivalent).  For
example, consider the preparsed string S1with(f:[ind,ind], forall(x:ind, #(f(x))))It parses into an internal expression E1 which is printed as the string S2
   with(f:[ind,ind],total_q{f,[ind,ind]})
with quasi-constructor abbreviations and is printed as S1 without
quasi-constructor abbreviations.  However, S2 parses into an
internal expression E2 which is printed as S2 with
quasi-constructor abbreviations and is printed as the string S3with(f:[ind,ind],forall(x_0:ind,#(f(x_0))))without quasi-constructor abbreviations. That is, the two internal expressions are the same except for the name of the single bound variable.
 -equivalent).
In this case, there is no problem; for the most part,  IMPS will
treat the expressions as if they were identical.  However, the two
expressions may differ in other ways, e.g., some of the corresponding
bound variables may have different sorts.  Hence, in rare occasions,
it may happen that there are two internal expressions printed the same
which are not known by  IMPS to be equal (or quasi-equal).  This
situation can be very hard to deal with.  It is often best to backup
and try a different path that will avoid this confusing situation.
-equivalent).
In this case, there is no problem; for the most part,  IMPS will
treat the expressions as if they were identical.  However, the two
expressions may differ in other ways, e.g., some of the corresponding
bound variables may have different sorts.  Hence, in rare occasions,
it may happen that there are two internal expressions printed the same
which are not known by  IMPS to be equal (or quasi-equal).  This
situation can be very hard to deal with.  It is often best to backup
and try a different path that will avoid this confusing situation.
 
 
 
 
 
 
