Curry: An Integrated Functional Logic Language
Curry: An Integrated Functional Logic Language
Curry: An Integrated Functional Logic Language
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
tion 3 with σ(t1 . . . tn) = σ(t ′ 1 . . . t′ n), then at least one of the following conditions holds:<br />
(a) σ(e) = σ(e ′ ) (compatibility of right-hand sides).<br />
(b) σ(c) and σ(c ′ ) are not simultaneously satisfiable (incompatibility of conditions). A decidable<br />
approximation of this condition can be found in [30].<br />
These conditions ensure the confluence of the rules if they are considered as a conditional term<br />
rewriting system [47]. Implementations of <strong>Curry</strong> may check these conditions and warn the user if<br />
they are not satisfied. There are also more general conditions to ensure confluence [47] which can<br />
be checked instead of the above conditions.<br />
Note that defining equations of higher-type, e.g., f = g if f and g are of type Bool -> Bool, are<br />
formally excluded in order to define a simple operational semantics based on first-order rewriting. 4<br />
For convenience, a defining equation f = g between functions is allowed but will be interpreted in<br />
<strong>Curry</strong> as syntactic sugar for the corresponding defining equation f x = g x on base types.<br />
2.3.1 Functions vs. Variables<br />
In lazy functional languages, different occurrences of the same variable are shared to avoid multiple<br />
evaluations of identical expressions. For instance, if we apply the rule<br />
double x = x+x<br />
to an expression double t, we obtain the new expression t+t but both occurrences of t denote the<br />
identical expression, i.e., these subterms will be simultaneously evaluated. Thus, several occurrences<br />
of the same variable are always shared, i.e., if one occurrence of an argument variable, which<br />
might bound to an evaluable expression when the function is applied, is evaluated to some value,<br />
all other occurrences of this variable are replaced by the same value (without evaluating these<br />
other occurrences again). This sharing is necessary not only for efficiency reasons but it has also<br />
an influence on the soundness of the operational semantics in the presence of non-deterministic<br />
functions (see also [18]). For instance, consider the non-deterministic function coin defined by the<br />
rules<br />
coin = 0<br />
coin = 1<br />
Thus, the expression coin evaluates to 0 or 1. However, the result values of the expression<br />
(double coin) depend on the sharing of the two occurrences of coin after applying the rule<br />
for double: if both occurrences are shared (as in <strong>Curry</strong>), the results are 0 or 2, otherwise (without<br />
sharing) the results are 0, 1, or 2. The sharing of argument variables corresponds to the so-called<br />
“call time choice” in the declarative semantics [18]: if a rule is applied to a function call, a unique<br />
value must be assigned to each argument (in the example above: either 0 or 1 must be assigned<br />
to the occurrence of coin when the expression (double coin) is evaluated). This does not mean<br />
3 A substitution σ is a mapping from variables into expressions which is extended to a homomorphism on expressions<br />
by defining σ(f t1 . . . tn) = f σ(t1) . . . σ(tn). {x1 ↦→ e1, . . . , xk ↦→ ek} denotes the substitution σ with σ(xi) = ei<br />
(i = 1, . . . , k) and σ(x) = x for all variables x �∈ {x1, . . . , xk}.<br />
4 Note that this is also necessary in an extension of <strong>Curry</strong> which allows higher-order rewrite rules, since rules with<br />
lambda-abstractions in left-hand sides which are not of base type may cause a gap between the standard notion of<br />
higher-order rewriting and the corresponding equational theory [41].<br />
6