Here's a execution trace for the call change [5,2] 16. The parts to the left
of handle represent what the function has computed thus far, while the part
on the right is the state to continue with when backtracking is requested via a Change signal.
> 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]
As you can see, when the Change exception is caught, the algorithm goes back two
stack frames, drops the third 5 coin from the result list and recurses only with
a 2 coin in the list of coins. The amount is also reset to 6.
The first line, the part before handle tries to use another 5 as a possible
decomposition, while the exception handler represents the backtracking option,
i.e., remove the 5 we've just tried and adjust the coin list and the remaining
amount.
The final line signals the last installed exception handler to backtrack.
> 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
In other words, the algorithm backtracks when it reaches a state where no more
coin types are available to choose, but the amount is still positive. It's greedy
because the algorithm will use the same coin until it catches an exception.
The exception handler is attached to the else expression because it's where
the greedy choice is made.
Hopefully I've been intelligible with my explanation.