Below is my first program in Curry. It prints sequence of steps required for reaching a desired solution (walking through a closed door).
Evaluating expression: main
Done
(Just [Open,Walk,Close])
How can I make it terminate when looking for Impossible? I am using Kics2 0.3.1.
import List
import AllSolutions
import IO
import ReadShowTerm
import Constraint
data State = Opened | Closed | Outside | Done | Impossible
data Action = Open | Walk | Close
e Open Closed = Opened
e Walk Opened = Outside
e Close Outside = Done
solution target | foldl (flip e) Closed actions =:= target & length actions <: 4 = actions
where actions free
main = do
target <- getContents
getOneValue (solution $ readTerm target) >>= print
In the case of
Done, you prune the search space by usinggetOneValue. That is, when the first result is found, the function does not generate more possibilities for the free variableactions. However, when there is no solution, like in the case ofImpossible, the use ofgetOneValuecannot prune the search space as it keeps on looking for the first solution. In fact, if you search for all solutions instead of only the first one, even the other call does not terminate after finding a solution.In order to get a terminating version, you could try the following definition of
solution.This way the search space is actually pruned because
takedoes only evaluate the first four cons constructors of the list. In contrast,lengthcauses the evaluation of all constructors of the list to calculate the length. Because it evaluates the whole list, the free variableactionsgenerates more and more lists, as the generation of non-deterministic possibilities of a free variable is driven by the evaluation of the free variable.Limiting the search space of a Curry program can be quite difficult because you have to reason about evaluation. For example, you also get a terminating program if you use peano numbers instead of primitive integers. More precisely, you can define the following functions using
Peanonumerals.By means of these functions you get a terminating version as follows.
However, note that you have to check for the length of the list first because
&has a left bias with respect to evaluation. That is, if its first argument fails, it does not evaluate its second argument. If we switch the arguments of&, the condition will first check whether the list of actions yields the stateClosedand afterwards check its length. That is, we do not use the length to prune the search space anymore.