虽然这只是代码的一部分,但可以解释为什么我会得到一个无限循环 这就是大步语义如何看起来像
eval (For iexp c, s)
|(bEval (Compare Leq iexp (IConst 0), s)) = s
|otherwise = eval (For n' c, s')
where
s' = eval(c,s)
n' = (IBin Minus iexp (IConst 1))
答案 0 :(得分:3)
无限循环最有可能来自代码的不同部分。你给出的片段看起来是正确的 - 并且 - 必要的类型和功能被适当地模拟 - 终止。
也许你没有正确评估减法?另一种可能性是bEval
无效。
这是Data.Trace
的一个很好的用例,它为调试提供了trace
函数。这就像使用print语句以任何其他语言调试一样。 (在内部,它使用unsafePerformIO
。)
trace
函数接受一个字符串和一个表达式;它打印字符串并返回表达式。还有一个traceShow
函数在打印前对其参数使用show
。
您可以使用它在循环执行时打印出中间值。我建议这样的事情:
eval (For iexp c, s)
| condition `traceShow` condition = s
| otherwise = n' `traceShow` eval (For n' c, s')
where condition = bEval (Compare Leq iexp (IConst 0), s)
s' = eval(c,s)
n' = (IBin Minus iexp (IConst 1))
这将在每一步打印出计数器的条件和值。这可以帮助您找出循环的来源。如果它没有,你可以移动跟踪语句,使用它们的方式与我在这里一样。