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.
Eval [e; rule(l | c = r)] ⇒ {id σ(c|r)}<br />
if σ is a substitution with σ(l) = e<br />
Eval [c] ⇒ D<br />
Eval [c|e] ⇒ replace(c|e, 1, D) Eval [success|e] ⇒ {id e}<br />
Figure 3: Evaluation of conditional rules<br />
always shared, i.e., if an argument of a function is instantiated during a call to this function to<br />
an expression and this expression is evaluated to some value (head normal form), then all other<br />
expressions resulting from instantiating occurrences of the same argument are replaced by the<br />
same value (head normal form). 21 This is necessary not only for efficiency reasons but also for the<br />
soundness of the operational semantics in the presence of non-deterministic functions, as discussed<br />
in Section 2.3.1. The sharing of variables can be described with the more complicated framework<br />
of graph rewriting. Formal descriptions of graph rewriting and narrowing can be found in [15, 18].<br />
D.3 Committed Choice<br />
To define the semantics of calls to functions with the evaluation annotation choice, we assume<br />
that all such calls are enclosed by choice(. . .). Now we extend the rules in Figures 2 and 3 for<br />
covering such choices. <strong>An</strong> expression choice(f(e1, . . . , en)) is reduced as follows. If<br />
Eval [f(e1, . . . , en)] ⇒ ∗ {. . . , σ success|ϕ(r), . . .}<br />
according to the operational semantics described in Figures 2 and 3, where l | c = r is a rule for<br />
f, 22 σ does not bind any free variable occurring in f(e1, . . . , en), and this is the first step in the<br />
derivation with this property, then Eval [choice(f(e1, . . . , en))] ⇒ {id ϕ(r)}.<br />
Thus, if disjunctions occur due to the evaluation of a call to a choice function, these disjunctions<br />
are not distributed to the top-level but are kept inside the choice expression. If one rule for<br />
the choice function becomes applicable (without binding of free variables in this call), all other<br />
alternatives in the disjunction are discarded. Hence, a call to a choice function corresponds to the<br />
committed choice (with deep guards) of concurrent logic languages. This can be implemented by<br />
evaluating this call (with a fair strategy for alternatives) as usual but with the restriction that only<br />
local variables can be bound.<br />
D.4 Equational Constraints<br />
<strong>An</strong> equational constraint e1=:=e2 is solvable if both sides are reducible to a unifiable data term<br />
(strict equality). <strong>An</strong> equational constraint can be solved in an incremental way by an interleaved<br />
21 It should be noted that values are constructor terms like 23, True, or [2,4,5]. This means that the evaluation<br />
of constraints and I/O actions are not shared since they are not replaced by a value after evaluation but<br />
constraints are solved in order to apply a conditional rule (in case of constraints) and I/O actions are applied<br />
to the outside world when they appear at the top-level in a program. This is the intended behavior since the<br />
expressions “putChar ’a’ >> putChar ’a’” and “let ca = putChar ’a’ in ca >> ca” should have an identical<br />
behvarior, namely printing the character ’a’ twice.<br />
22 <strong>An</strong> unconditional rule l = r is considered here as an abbreviation for l | success = r.<br />
68