Curry: An Integrated Functional Logic Language
Curry: An Integrated Functional Logic Language
Curry: An Integrated Functional Logic Language
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
instance, if we want to compute the last element of the list [3,4,5] based on append, we could try<br />
to solve the search goal<br />
\e -> append l [e] =:= [3,4,5]<br />
However, the evaluation of this goal suspends due to the necessary binding of the free variable l.<br />
This can be avoided by declaring the variable l as local to the constraint by the use of let (see<br />
Section 2.5), like in the following expression:<br />
first \e -> let l free in append l [e] =:= [3,4,5]<br />
Due to the local declaration of the variable l (which corresponds logically to an existential quantification),<br />
the variable l is only visible inside the constraint and, therefore, it can be bound to<br />
different values in different branches. Hence this expression evaluates to the result 5.<br />
In order to ensure that an encapsulated search will not be suspended due to necessary bindings<br />
of free variables, the search goal should be a closed expression when a search operator is applied<br />
to it, i.e., the search variable is bound by the lambda abstraction and all other free variables are<br />
existentially quantified by local declarations.<br />
8.3 Predefined Search Operators<br />
There are a number of search operators which are predefined in the prelude. All these operators are<br />
based on the primitive try as described above. It is also possible to define other search strategies<br />
in a similar way. Thus, the try operator is a a powerful primitive to define appropriate search<br />
strategies. In the following, we list the predefined search operators.<br />
solveAll :: (a->Success) -> [a->Success]<br />
Compute all solutions for a search goal via a depth-first search strategy. If there is no solution<br />
and the search space is finite, the result is the empty list, otherwise the list contains solved<br />
search goals (i.e., without defined operations).<br />
once :: (a->Success) -> (a->Success)<br />
Compute the first solution for a search goal via a depth-first search strategy. Note that once<br />
is partially defined, i.e., if there is no solution and the search space is finite, the result is<br />
undefined.<br />
findall :: (a->Success) -> [a]<br />
Compute all solutions for a search goal via a depth-first search strategy and unpack the<br />
solution’s values for the search variable into a list.<br />
best :: (a->Success) -> (a->a->Bool) -> [a->Success]<br />
Compute the best solution via a depth-first search strategy, according to a specified relation<br />
(the second argument) that can always take a decision which of two solutions is better<br />
(the relation should deliver True if the first argument is a better solution than the second<br />
argument).<br />
As a trivial example, consider the relation shorter defined by<br />
shorter l1 l2 = length l1