以下是我在库里的第一个节目。它打印到达所需解决方案所需的一系列步骤(走过关闭的门)。
Evaluating expression: main
Done
(Just [Open,Walk,Close])
如何在寻找Impossible
时终止它?我正在使用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
答案 0 :(得分:0)
如果是Done
,则使用getOneValue
修剪搜索空间。也就是说,当找到第一个结果时,该函数不会为自由变量actions
生成更多可能性。但是,当没有解决方案时,如Impossible
的情况,使用getOneValue
无法修剪搜索空间,因为它一直在寻找第一个解决方案。实际上,如果您搜索所有解决方案而不是仅搜索第一个解决方案,那么在找到解决方案之后,即使是另一个呼叫也不会终止。
要获得终止版本,您可以尝试以下solution
的定义。
solution target | foldl (flip e) Closed (take 4 actions) =:= target = actions
where actions free
这样,搜索空间实际上被修剪,因为take
仅评估列表的前四个cons构造函数。相反,length
导致对列表中所有构造函数的求值来计算长度。因为它评估整个列表,所以自由变量actions
生成越来越多的列表,因为自由变量的非确定性可能性的生成是由自由变量的评估驱动的。
限制Curry程序的搜索空间可能非常困难,因为您必须推理评估。例如,如果使用peano数而不是原始整数,也可以获得终止程序。更准确地说,您可以使用Peano
数字定义以下函数。
data Peano = Zero | Succ Peano
fourP :: Peano
fourP = Succ (Succ (Succ (Succ Zero)))
lengthP :: [a] -> Peano
lengthP [] = Zero
lengthP (_:xs) = Succ (lengthP xs)
lessP :: Peano -> Peano -> Success
lessP Zero (Succ _) = success
lessP (Succ x) (Succ y) = lessP x y
通过这些功能,您可以获得如下的终止版本。
solution target | lessP (lengthP actions) fourP & foldl (flip e) Closed actions =:= target = actions
where actions free
但是,请注意,您必须首先检查列表的长度,因为&
在评估方面存在左偏差。也就是说,如果它的第一个参数失败,它就不会评估它的第二个参数。如果我们切换&
的参数,则条件将首先检查操作列表是否产生状态Closed
,然后检查其长度。也就是说,我们不再使用长度来修剪搜索空间。