Functional programming 标准ML:回溯混淆

Functional programming 标准ML:回溯混淆,functional-programming,sml,Functional Programming,Sml,我被哈珀在第页的SML简介中给出的一个例子弄糊涂了。110他正在编写一个函数,对硬币价值列表进行一定量的更改,必要时进行回溯 e、 g.如果我运行change[5,2]16,我会得到[5,5,2,2,2](如果可能,算法应该是贪婪的) 有几个问题: 1) 我对这个算法如何实现回溯有点困惑。看起来,当使用硬币值的空列表作为第一个参数调用change时,它会引发change异常 但是更改异常处理程序调用Change。这是如何“推翻最近的贪婪决定”的 2) 为什么处理程序被放在else子句中?我原以为

我被哈珀在第页的SML简介中给出的一个例子弄糊涂了。110他正在编写一个函数,对硬币价值列表进行一定量的更改,必要时进行回溯

e、 g.如果我运行change[5,2]16,我会得到[5,5,2,2,2](如果可能,算法应该是贪婪的)

有几个问题:

1) 我对这个算法如何实现回溯有点困惑。看起来,当使用硬币值的空列表作为第一个参数调用change时,它会引发change异常

但是更改异常处理程序调用
Change
。这是如何“推翻最近的贪婪决定”的

2) 为什么处理程序被放在else子句中?我原以为它是完全独立的

谢谢你的帮助,
b外行

这里是调用的执行跟踪
change[5,2]16
of
handle
表示函数迄今为止已计算的内容,而 右侧是通过
更改
信号请求回溯时要继续的状态

> change [5, 2] 16
> 5 :: change [5, 2] (16 - 5)                 handle Change: change [2] 16
> 5 :: change [5, 2] 11                       handle Change: change [2] 16
> 5 :: 5 :: change [5, 2] (11 - 5)            handle Change: 5 :: change [2] 11
> 5 :: 5 :: change [5, 2] 6                   handle Change: 5 :: change [2] 11
> 5 :: 5 :: 5 :: change [5, 2] (6 - 5)        handle Change: 5 :: 5 :: change [2] 6
> 5 :: 5 :: 5 :: change [5, 2] 1              handle Change: 5 :: 5 :: change [2] 6
> 5 :: 5 :: 5 :: change [2] 1
> 5 :: 5 :: 5 :: change nil 1
> raise Change => 5 :: 5 :: change [2] 6
> 5 :: 5 :: 2 :: change [2] (6 - 2)           handle Change
> 5 :: 5 :: 2 :: change [2] 4                 handle Change
> 5 :: 5 :: 2 :: 2 :: change [2] (4 - 2)      handle Change
> 5 :: 5 :: 2 :: 2 :: change [2] 2            handle Change
> 5 :: 5 :: 2 :: 2 :: 2 :: change [2] (2 - 2) handle Change
> 5 :: 5 :: 2 :: 2 :: 2 :: change [2] 0       handle Change
> 5 :: 5 :: 2 :: 2 :: 2 :: nil
> [5, 5, 2, 2, 2]
正如您所看到的,当捕获到更改异常时,算法返回两步 堆叠帧,从结果列表中丢弃第三个5硬币,并仅使用 硬币列表中的2枚硬币。金额也重置为6

第一行,
handle
前面的部分尝试使用另一个5作为可能的参数 分解,而异常处理程序表示回溯选项, i、 例如,移除我们刚刚尝试过的5个硬币,调整硬币列表和剩余的硬币 数量

最后一行通知最后安装的异常处理程序返回

> 5 :: 5 :: 5 :: change [5, 2] 1              handle Change: 5 :: 5 :: change [2] 6
> 5 :: 5 :: 5 :: change [2] 1
> 5 :: 5 :: 5 :: change nil 1
> raise Change => 5 :: 5 :: change [2] 6
换言之,当算法达到不再需要的状态时,它会进行回溯 硬币类型可以选择,但数量仍然是正数。这是贪婪的 因为在捕获异常之前,算法将使用相同的硬币

异常处理程序附加到
else
表达式,因为它位于 贪婪的选择已经做出

希望我的解释能被理解

> 5 :: 5 :: 5 :: change [5, 2] 1              handle Change: 5 :: 5 :: change [2] 6
> 5 :: 5 :: 5 :: change [2] 1
> 5 :: 5 :: 5 :: change nil 1
> raise Change => 5 :: 5 :: change [2] 6