Продолжение прохождения стиля-функциональная композиция
Я изучаю CPS с помощью Racket, и мне удалось записать следующие функции:
;lift a regular single-arg function into CPS
(define (lift/k f)
(lambda (x k)
(k (f x))))
;compose two CPS functions
(define (compose/k f g)
(lambda (x k)
(g x (lambda (y)
(f y k)))))
Они, кажется, работают правильно
(define (is-two/k x k)
(k (= x 2)))
(define is-not-two/k (compose/k (lift/k not) is-two/k))
(is-not-two/k 3 display)
(is-not-two/k 2 display)
#t#f
Мне интересно, являются ли эти функции все еще"истинными CPS". Не испортил ли я" истинное " продолжение-прохождение с этими функциями? Кошерно ли использовать методы функциональной композиции в CPS? Это поощряется? Или это будет считаться "компромиссом"? Есть ли более CPS-y способ сделать это?
Да, я знаю, что только что задал 5 вопросов, но основная идея, стоящая за ними всеми (которую я не уверен, что правильно понимаю), одна и та же. Объяснения в других шепелявит, Хаскель, Эрланг, или другие функциональные языки хорошо.
1 ответ:
Преобразование типа продолжения-передачи может быть частичным или полным. Вы обычно работаете с системой, где некоторые примитивы ( + , - и т. д.) застряли в ХП-земля. К счастью, CPS работает нормально в любом случае.
Шаги в CPSing:
Выберите, какие функции будут примитивными. CPS-преобразование так, что все непримитивные функции (включая продолжения) вызываются только в хвостовой позиции.
Итак, в вашем коде ваш 'lift/k' равен по существу, рассматривая его данную функцию как примитивную: обратите внимание, что тело lift/k вызывает 'f' в не-хвостовом положении. Если вы не хотите рассматривать поднятую функцию как примитив, вы должны пойти и переписать ее явно.
Ваша функция "compose" составляет две CPSed-функции, но сама не находится в CPS (то есть вы предполагаете, что "compose" примитивен. Вы, вероятно, хотите, чтобы CPS его. Обратите внимание, что поскольку он просто возвращает значение сразу, это просто:
;compose two CPS functions (define (compose/k f g k) (k (lambda (x k) (g x (lambda (y) (f y k))))))