1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
------------------------------------------------------------------------------
-- | Library with operations to encapsulate search, i.e., to return all or
-- some values of an expression containing non-deterministic computations
-- in a data structure.
-- Note that these operations are not fully declarative, i.e.,
-- the results depend on the order of evaluation and program rules.
-- This is due to the fact that the search operators work on a copy
-- of the current expression to be encapsulated.
-- The potential problems of this method are discussed in this paper:
--
-- > B. Brassel, M. Hanus, F. Huch:
-- > Encapsulating Non-Determinism in Functional Logic Computations
-- > Journal of Functional and Logic Programming, No. 6, EAPLS, 2004
--
-- There are newer and better approaches the encapsulate search,
-- in particular, set functions (see module `Control.Search.SetFunctions`)
-- which should be used.
--
-- Author : Michael Hanus
-- Version: October 2026
------------------------------------------------------------------------------
{-# LANGUAGE CPP #-}

module Control.Search.Unsafe
  ( allValues, allValuesDFS, oneValue, oneValueDFS, someValue, isFail
  , rewriteAll, rewriteSome
  ) where





------------------------------------------------------------------------------

-- | Returns all values of an expression.
-- Conceptually, the value is computed on a copy of the expression,
-- i.e., the evaluation of the expression does not share any results.
--
-- The strategy to search for all values depends on the Curry system:
--
-- * PAKCS uses a depth-first search strategy and computes all values at once,
-- * KiCS2 uses a breadth-first search strategy and computes all values lazily.
-- * KMCC uses a fair search strategy and computes all values lazily.
-- * Curry2Go uses a fair search strategy and computes all values lazily.
--
-- In PAKCS, the evaluation suspends as long as the expression
-- or its computed value contain unbound variables.
--
-- Note that this operation is not purely declarative since the ordering
-- of the computed values depends on the ordering of the program rules.
allValues :: a -> [a]



allValues external


-- | Returns all values of an expression.
-- This operation is similar to 'allValues' but uses a depth-first search
-- strategy (if available).
-- Thus, it could be more efficient than 'allValues' but it might
-- not terminate (instead of computing of all values) if the search space
-- is infinite.
allValuesDFS :: a -> [a]



allValuesDFS x = allValues x  -- PAKCS supports only depth-first search






-- | Returns just one value for an expression or `Nothing`
-- if the expression has no value.
-- Conceptually, the value is computed on a copy of the expression,
-- i.e., the evaluation of the expression does not share any results.
--
-- The strategy to search for a value depends on the Curry system:
--
-- * PAKCS uses a depth-first search strategy,
-- * KiCS2 uses a breadth-first search strategy, and
-- * KMCC uses a fair search strategy.
-- * Curry2Go uses a fair search strategy.
--
-- In PAKCS, the evaluation suspends as long as the expression
-- or its computed value contain unbound variables.
--
-- Note that this operation is not purely declarative since
-- the computed value depends on the ordering of the program rules.
-- Thus, this operation should be used only if the expression
-- has at most one value.
oneValue :: a -> Maybe a





oneValue external


-- | Returns just one value for an expression or `Nothing`
-- if the expression has no value.
-- This operation is similar to 'oneValue' but uses a depth-first search
-- strategy (if available).
-- Thus, it could be more efficient than 'oneValue' but it might not terminate
-- (instead of computing of value) if the search space is infinite.
oneValueDFS :: a -> Maybe a





oneValueDFS x = oneValue x  -- PAKCS supports only depth-first search






-- | Returns some value for an expression.
-- If the expression has no value, the computation fails.
-- Conceptually, the value is computed on a copy of the expression,
-- i.e., the evaluation of the expression does not share any results.
--
-- In PAKCS, the evaluation suspends as long as the expression
-- or its computed value contain unbound variables.
--
-- Note that this operation is not purely declarative since
-- the computed value depends on the ordering of the program rules.
-- Thus, this operation should be used only if the expression
-- has a single value.
someValue :: a -> a
someValue x = case oneValue x of Just v  -> v
                                 Nothing -> failed

-- | Does the computation of the argument to a value fail?
-- Thus, `isFail e` returns `True` if the expression `e`
-- has no value. For instance, `isFail (head [])` evaluates to `True`.
--
-- Conceptually, the argument is evaluated on a copy, i.e.,
-- even if the computation does not fail, it has not been evaluated.
isFail :: a -> Bool
isFail x = case oneValue x of Nothing -> True
                              Just _  -> False

------------------------------------------------------------------------------
-- | Gets all values computable by term rewriting.
-- In contrast to `allValues`, this operation does not wait
-- until all "outside" variables are bound to values,
-- but it returns all values computable by term rewriting
-- and ignores all computations that requires bindings for outside variables.
rewriteAll :: a -> [a]

rewriteAll external




-- | Similarly to 'rewriteAll' but returns only some value computable
-- by term rewriting. Returns `Nothing` if there is no such value.
rewriteSome :: a -> Maybe a

rewriteSome external




------------------------------------------------------------------------------