В простых случаях с функциональными языками часто бывает полезно написать выражение в форме, подобной лямбда-исчислению, и выполнить сокращения вручную (отмечая, какие сокращения вы используете). Вы по-прежнему можете использовать синтаксис OCaml в качестве упрощенной версии лямбда-исчисления
Так что в случае вашего примера это будет:
let test a x = ((fun a -> a ) x);;
=> let test a x = ((fun b -> b ) x);; (* Variable renamed (alpha equivalence) *)
=> let test a y = ((fun b -> b ) y);; (* Variable renamed (alpha equivalence) *)
let func x = x + x;;
Обратите внимание, что эти шаги служат только для гарантии того, что в дальнейшем у нас не будет переменных с одинаковым именем, ссылающихся на разные значения. Эти шаги можно пропустить, но мне лично больше нравится работать с уникальными переменными.
test func 5
=> test (fun x -> x + x) 5 (* Variable func inserted (beta reduction) *)
=> (fun a y -> ((fun b -> b) y) (fun x -> x + x) 5 (* Variable test inserted *)
=> (fun y -> (fun b -> b) y) 5 (* Variable a inserted *)
=> ((fun b -> b) 5 (* Variable y inserted *)
=> 5 (* Variable b inserted *)
Окончательный результат - 5
. Попытка сделать это на первый взгляд может показаться очень необычной и сложной, но все становится проще и быстрее. Если вы сделаете что-то подобное пару раз, вы станете намного лучше в понимании общих функциональных шаблонов и рассуждениях о структуре вашей программы.
Посмотрите эту статью , чтобы получить больше примеров по этому вопросу.
Также обратите внимание, что при небольшом усилии это работает и в обратном направлении. Хотя обычно это не так полезно, как делать это в том же направлении, что и компилятор.