fun intf base next 0 = base
| intf base next n = next (n, (intf base next (n-1)));
val iota = intf [0] (op ::);
local
val append = foldl (op @) []
fun repeat x = intf [] (fn (_,ls) => x::ls)
fun rep2each x n ls = map (fn e => (repeat x n) @ e) ls
in
fun change nil 0 = [[]]
| change nil _ = []
| change (c::cs) x =
append (map (fn n => rep2each c n (change cs (x - n*c)))
(iota (x div c)))
end;
####
datatype 'a option = Solution of 'a | Nothing;
####
fun sflat ls = foldr (fn (Solution x, _) => Solution x
| (Nothing,v) => v)
Nothing ls;
fun smap _ Nothing = Nothing | smap f (Solution x) = Solution (f x)
####
local
fun repeat x = intf [] (fn (_,ls) => x::ls)
in
fun change1 nil 0 = Solution []
| change1 nil _ = Nothing
| change1 (c::cs) x =
sflat (map (fn n => smap (fn x => (repeat c n) @ x) (change1 cs (x - n*c)))
(iota (x div c)))
end;
####
local val addup = foldr (fn (a,b) => a+b) 0
in
fun countchange nil 0 = 1
| countchange nil _ = 0
| countchange (c::cs) x =
addup (map (fn n => countchange cs (x - n*c))
(iota (x div c)))
end;