Defines functions for working with expression functions and their applications
Let $\mathcal{L}$ be the set of expressions in a language. Here, we will think of $\mathcal{L}$ as all possible Expressions, in the technical sense of that word (not just saying "expression" informally, but now referring to instances of the Expressions class).
An Expression Function (or EF for short) is a function whose signature is $f:\mathcal{L}^n\to\mathcal{L}$ for some $n\in\mathbb{N}$. We need a way to represent Expression Functions as LogicConcepts. This module provides functions that let us do so.
We will write an Expression Function using standard $\lambda$ notation, as in
$\lambda v_1,\ldots,v_n.B$, where each $v_i$ is a parameter to the function
(represented using a Symbol with the name v_1
, v_2
, etc.))
and the body $B$ is any Expression that may contain free
instances of the $v_i$ that can be replaced with other
Expressions when the function is applied to arguments.
For example, if $f=\lambda v_1,v_2.v_1+\cos(v_2+1)$, then we could apply $f$
to the Expressions $3$ and $k$ to obtain the new
Expression $3+\cos(k+1)$.
The above paragraph uses ordinary mathematical notation, but we will need to
be able to write expression functions in
putdown notation so that we can express
them as LogicConcepts. We define a constant in this
module to be "LDE lambda"
so that we can express the $f$ from above as
("LDE lambda" v_1 , v_2 , (+ v_1 (cos (+ v_2 1))))
.
That constant may change in later versions of the LDE, so clients should not
hard-code that name into their code, but instead use
newEF() and
isAnEF().
You can also check the number of arguments of an expression function with arityOfEF() and apply them with applyEF(). And you can create simple types of expression functions with constantEF() and projectionEF().
An Expression Function Application (or EFA for short) is an
Expression expressing the idea that we are applying some
Expression Function to a list of arguments. For example, the application
above was $f(3,k)$, but we cannot write this in
putdown notation as (f 3 k)
because that
would be indistinguishable from normal function application. Thus we need a
new symbol. We define a constant in this module to be "LDE EFA"
so that we
can express $f(3,k)$ as ("LDE EFA" f 3 k)
. That constant may change in
later versions of the LDE, so clients should not hard-code that name into
their code, but instead use newEFA()
and isAnEFA(). You can also check
whether an EFA is evaluatable with
canBetaReduce() and evaluate
it (or any possible $\beta$-reduction inside it) with
betaReduce() and
fullBetaReduce().
Since we have functions in this module for $\beta$-reduction, we also have two related to $\alpha$-equivalence. You can check if two expressions are $\alpha$-equivalent with alphaEquivalent() and you can convert a binding to an $\alpha$-equivalent version of itself by renaming its variables, using alphaRenamed().
Source
Members
alphaEquivalent
Two expressions are $\alpha$-equivalent if renaming the bound variables in one makes it exactly equal to the other. For example, $\forall x,R(x,2)$ is $\alpha$-equivalent to $\forall y,R(y,2)$, but not to $\forall y,R(y,y)$.
Source
alphaRenamed
Perform $\alpha$-renaming on a binding, producing a new MathConcept that is $\alpha$-equivalent to the original, but with different names for the bound variables.
If you pass an argument to the binding
parameter that does not pass the
binds() test, the result of this function is
undefined.
Source
applicationEF
Construct a function whose body is an application of the form shown below. The caller provides the arity of the function as well as a list of symbols to be used in constructing the function's body, as shown below. Assume the given arity is $n$ and the list of symbols given is $F_1,\ldots,F_m$. Further assume that the symbol used to indicate an EFA (as defined here) is $A$. Then the expression function created will be $$ \lambda v_1,\ldots,v_n.((A~F_1~v_1~\cdots~v_n)~\cdots~(A~F_m~v_1~\cdots~v_n)). $$ This particular form is useful in the matching algorithm in the Problem class. The bound variables will be chosen so that none of them is equal to any of the symbols $F_1,\ldots,F_m$.
Source
applyEF
Applies ef
as an expression function to a list of arguments. If ef
is
not an expression function (as per
isAnEF()) or the list of arguments
is the wrong length, an error is thrown. Otherwise, a copy of the body of
ef
is returned with all parameters substituted with arguments.
For example, if ef
is an Expression representing
$\lambda v_1,v_2.\sqrt{v_1^2+v_2^2}$ and A
another representing $x-1$ and
B
another representing $y+1$, then applyEF(ef,A,B)
would be a newly
constructed Expression instance (sharing no subtrees with
any of those already mentioned) representing $\sqrt{(x-1)^2+(y+1)^2}$.
No check is made regarding whether this might cause variable capture, and no
effort is made to do $\alpha$-substitution to avoid variable capture. Thus
this routine is of limited value; it should be used only in situations where
the caller knows that no variable capture will take place. For example, if
ef
is $\lambda v.\sum_{i=1}^n i^v$ then applyEF(ef,i)
is
$\sum_{i=1}^n i^i$. No error is thrown; the capture simply happens.
See
Source
arityOfEF
Compute the arity of a given expression function. If ef
is not an
expression function (as judged by
isAnEF()) then an error is thrown.
Otherwise, a positive integer is returned representing the arity of the given
function, 1 for a unary function, 2 for a binary function, etc.
Source
betaReduce
If canBetaReduce() returns true, we may want to act upon that and perform the $\beta$-reduction. This function does so. It requires an argument that passes the canBetaReduce() test, and it will perform exactly one step of $\beta$-reduction. That is, it will substitute the arguments of the expression function application into (a copy of) the body of the expression function and return the result.
Note that the process of $\beta$-reduction is usually considered to be the repetition of this process in all possible ways until it termintes (if it does). That process is implemented in the function fullBetaReduce(). This function does just one step.
Source
bodyOfEF
Get the body of a given expression function. If ef
is not an expression
function (as judged by
isAnEF()) then an error is thrown.
Otherwise, its function body returned, which is one of its descendants.
Source
canBetaReduce
An expression can be $\beta$-reduced if it is an expression function application and the expression function in question is not a metavariable, but an actual expression function. To help distinguish these two possibilities, consider:
- If
P
is a metavariable andx
is a Symbol, we could create an expression function application with, for example,newEFA(P,new Symbol(5))
, but we could not evaluate it, because we do not know the meaning ofP
. - If
f
is an expression function, that is, it would pass the testisAnEF(f)
defined here, andx
is as above, then (assuming the arity off
is 1) the expressionnewEFA(f,new Symbol(5))
can be evaluated, becausef
has a body and we can substitute 5 into its body in the appropriate places.
Thus we need a function to distinguish these two cases. Both will pass the
test isAnEFA(), but only one can
be applied. Such application is called $\beta$-reduction, so we have this
function canBetaReduce()
that can detect when we are in the second case,
above, rather than the first. That is, does the expression being applied
pass the isAnEF() test, or is it
just a metavariable? This function returns true only in the former case,
plus it also verifies that the correct number of arguments are present; if
not, it returns false for that reason.
Examples:
canBetaReduce(newEFA(metavar,arg))
returns falsecanBetaReduce(newEFA(newEF(symbol,body),arg))
returns truecanBetaReduce(newEFA(newEF(symbol,body),too,many,args))
returns false
Source
constantEF
Create an expression function (as defined here) that is a constant function (that is, it always returns the same expression). That is, the function can be expressed as $\lambda v_1,\ldots,v_n. E$ for some expression $E$ not containing any of the $v_i$. The variables will have names chosen so that none of them appears free in $E$.
Source
expressionFunction
The constant used in this module as the operator when encoding Expression Functions as LogicConcepts. See the documentation at the top of this module for more information.
Source
expressionFunctionApplication
The constant used in this module as the operator when encoding Expression Function Applications as LogicConcepts. See the documentation at the top of this module for more information.
Source
fullBetaReduce
Make a copy of the given Expression, then find inside it all subexpressions passing the test in canBetaReduce(), and apply each such $\beta$-reduction using betaReduce(). Continue this process until there are no more opportunities for $\beta$-reduction.
This process is, in general, not guaranteed to terminate. Clients should take care to call it only in situations where it is guaranteed to terminate. For example, the following expression function application will $\beta$-reduce to itself, and thus enter an infinite loop. $$ ((\lambda v. (v~v))~(\lambda v. (v~v))) $$ In the LDE, we are unlikely to permit users to write input that requires us to apply expression functions to other expression functions, thus preventing cases like this one.
Source
isAnEF
Test whether the given Expression encodes an Expression Function, as defined by the encoding documented at the top of this file, and as produced by the function newEF().
See
Source
isAnEFA
Test whether the given expression encodes an Expression Function Application, as defined by the encoding documented at the top of this file, and as produced by the function newEFA().
See
Source
newEF
Creates a new expression function, encoded as a LogicConcept, as described at the top of this file. The arguments are not copied; if you do not wish them removed from their existing contexts, pass copies to this function.
For example, if x
and y
are Symbol instances with the
names "x" and "y" and B
is an Application, such as (+ x y)
, then
newEF(x,y,B)
will be the Expression
("LDE lambda" (x y) , (+ x y))
.
See
Source
newEFA
Creates a new Expression Function Application, encoded as an Expression, as described at the top of this file. The arguments are not copied; if you do not wish them removed from their existing contexts, pass copies to this function.
For example, if F
is an Expression representing an
Expression Function (or a metavariable that might later be instantiated as
one) and x
and y
are any other Expressions (let's just
say the symbols "x" and "y" for this example) then newEFA(F,x,y)
will be
the Expression ("LDE EFA" F x y)
.
If the first argument is a metavariable then there must be one or more additional arguments of any type. If the first argument is an Expression Function (as per isAnEF()) then there must be a number of arguments following it that are equal to its arity. If these rules are not followed, an error is thrown.
See
Source
parametersOfEF
Get the list of parameters for a given expression function. If ef
is not
an expression function (as judged by
isAnEF()) then an error is thrown.
Otherwise, an array of its parameters is returned, the exact descendants that
are Symbol instances.
Source
projectionEF
Create an expression function (as defined here) that returns one of its arguments. That is, the function can be expressed as $\lambda v_1,\ldots,v_n. v_i$ for some $i$ between 1 and $n$.