Первый шаг - превратить ваш набор уравнений верхнего уровня для foldl
в лямбда-выражение, которое использует анализ случая, например:
val rec foldl = fn f => fn b => fn lst =>
case lst of [] => b
| (h::t) => foldl f (f(h,b)) t
Теперь вы можете использовать ту же логику, что и раньше. Взяв в качестве примера функцию fn (x, y) => x * y
, мы можем видеть, что
val prod = foldl (fn (x, y) => x * y)
эквивалентно
val prod = (fn f => fn b => fn lst =>
case lst of [] => b
| (h::t) => foldl f (f(h,b)) t) (fn (x, y) => x * y)
который бета-уменьшает до
val prod = fn b => fn lst =>
case lst of [] => b
| (h::t) => foldl (fn (x, y) => x * y) ((fn (x, y) => x * y)(h,b)) t
, бета-версия которого уменьшается до
val prod = fn b => fn lst =>
case lst of [] => b
| (h::t) => foldl (fn (x, y) => x * y) (h * b) t
Теперь, поскольку мы знаем из нашего первого определения, что prod
эквивалентно foldl (fn (x, y) => x * y)
, мы можем подставить его в его собственное определение:
val rec prod = fn b => fn lst =>
case lst of [] => b
| (h::t) => prod (h * b) t
Затем мы можем мысленно преобразовать это обратно в функцию, определяемую уравнениями, если нам нравится:
fun prod b [] = b
| prod b (h::t) = prod (h * b) t
Это то, что вы ожидаете, верно?