14.11.2012 Views

Curry: An Integrated Functional Logic Language

Curry: An Integrated Functional Logic Language

Curry: An Integrated Functional Logic Language

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

side of some rule, if the left-hand side has a constructor at this position, i.e., in order to apply the<br />

rule, the actual value at this position must be the constructor). In this situation there are two<br />

possibilities to proceed:<br />

1. Delay the evaluation of this function call until the corresponding free variable is bound (this<br />

corresponds to the residuation principle which is the basis of languages like Escher [31, 32],<br />

Le Fun [2], Life [1], NUE-Prolog [40], or Oz [46]). In this case, the function is called rigid.<br />

2. (Non-deterministically) instantiate the free variable to the different values demanded by the<br />

left-hand sides and apply reduction steps using the different rules (this corresponds to narrowing<br />

principle which is the basis of languages like ALF [20], Babel [37], K-Leaf [17], LPG<br />

[8], or SLOG [16]). In this case, the function is called flexible.<br />

Since <strong>Curry</strong> is an attempt to provide a common platform for different declarative programming<br />

styles and the decision about the “right” strategy depends on the definition and intended meaning<br />

of the functions, <strong>Curry</strong> supports both strategies. The precise strategy is specified by evaluation<br />

annotations for each function. 6 The precise operational meaning of evaluation annotations is<br />

defined in Appendix D. A function can be explicitly annotated as rigid. If an explicit annotation<br />

is not provided by the user, a default strategy is used: functions with the result type “IO ...” are<br />

rigid and all other defined functions are flexible. Functions with a polymorphic result type (like the<br />

identity) are considered as flexible, although they can be applied like a function with result type<br />

“IO ...” in a particular context. For each external function, i.e., a function that is not defined<br />

by explicit program rules, the strategy is also fixed. Most predefined functions, like arithmetic<br />

operators (see Section 4.1.4), are rigid, i.e., they suspend if some argument is an unbound variable.<br />

For instance, consider the function f as defined above. As the default strategy, f is flexible, i.e.,<br />

the expression f x is evaluated by instantiating x to 0 or 1 and applying a reduction step in both<br />

cases. This yields the disjunctive expression<br />

{x=0} 2 | {x=1} 3 .<br />

However, if f has the evaluation annotation<br />

f eval rigid<br />

(i.e., f is rigid), then the expression f x cannot be evaluated since the argument is a free variable.<br />

In order to proceed, we need a “generator” for values for x, which is the case in the following<br />

constraint:<br />

f x =:= y & x =:= 1<br />

Here, the first constraint f x =:= y cannot be evaluated and thus suspends, but the second constraint<br />

x=:=1 is evaluated by binding x to 1. After this binding, the first constraint can be evaluated<br />

and the entire constraint is solved. Thus, the constraint is solved by the following steps:<br />

f x =:= y & x =:= 1<br />

❀ {x=1} f 1 =:= y<br />

❀ {x=1} 3 =:= y<br />

6 Evaluation annotations are similar to coroutining declarations [39] in Prolog where the programmer specifies<br />

conditions under which a literal is ready for a resolution step.<br />

13

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!