В чем разница между стилем продолжения прохождения (cps) и монадами.
Продолжение стиля прохода против монад
Ответ 1
Как упоминалось в Суть функционального программирования:
Программирование с монадами, сильно напоминающими стиль продолжения прохождения (CPS), и в этой статье рассматривается взаимосвязь между ними. В каком-то смысле они эквивалентны: CPS возникает как частный случай монады, и любая монада может быть встроена в CPS путем изменения типа ответа. Но монадический подход обеспечивает дополнительную проницательность и обеспечивает более высокую степень контроля.
Эта статья довольно строгая, и на самом деле она не совсем расширяет связь между CPS и монадами. Здесь я попытаюсь дать неформальный, но иллюстративный пример:
(Примечание: ниже понимается Monad от новичка (я), хотя после его написания он, похоже, выглядит как один из тех ответов высокопоставленных пользователей. Пожалуйста, возьмите его с тонны соли)
Рассмотрим классическую монаду Maybe
-- I don't use the do notation to make it
-- look similar to foo below
bar :: Maybe Int
bar =
Just 5 >>= \x ->
Just 4 >>= \y ->
return $ x + y
bar' :: Maybe Int
bar' =
Just 5 >>= \x ->
Nothing >>= \_ ->
return $ x
GHCi> bar
Just 9
GHCi> bar'
Nothing
Итак, вычисление прекращается, как только встречается Nothing
, здесь ничего нового. Попробуйте воспроизвести такое монадическое поведение с помощью CPS:
Вот наша функция vanilla add
, использующая CPS. Мы используем здесь все Int
вместо алгебраического типа данных, чтобы упростить его:
add :: Int -> Int -> (Int -> Int) -> Int
add x y k = k (x+y)
GHCi> add 3 4 id
7
Обратите внимание, как это похоже на монаду
foo :: Int
foo =
add 1 2 $ \x -> -- 3
add x 4 $ \y -> -- 7
add y 5 $ \z -> -- 12
z
GHCi> foo
12
OK. Предположим, что мы хотим, чтобы вычисление было ограничено на 10. То есть любое вычисление должно прекратиться, когда следующий шаг приведет к значению, превышающему 10. Это похоже на высказывание "Может быть, вычисление должно остановиться и вернуть Nothing
как скоро, как любое значение в цепочке Nothing
). Посмотрим, как мы можем это сделать, написав" трансформатор CPS"
cap10 :: (Int -> Int) -> (Int -> Int)
cap10 k = \x ->
if x <= 10
then
let x' = k x in
if x' <= 10 then x' else x
else x
foo' :: Int
foo' =
add 1 2 $ cap10 $ \x -> -- 3
add x 4 $ cap10 $ \y -> -- 7
add y 5 $ cap10 $ \z -> -- 12
undefined
GHCi> foo'
7
Обратите внимание, что конечное возвращаемое значение может быть undefined
, но это нормально, потому что оценка останавливается на 3-м шаге (z
).
Мы видим, что cap10
"обертывает" нормальное продолжение некоторой дополнительной логикой. И это очень близко к тому, что monad to - склеивание вычислений вместе с некоторой дополнительной логикой.
Отпустите еще один шаг:
(>>==) :: ((Int -> Int) -> Int) -> (Int -> Int) -> Int
m >>== k = m $ cap10 k
foo'' :: Int
foo'' =
add 1 2 >>== \x -> -- 3
add x 4 >>== \y -> -- 7
add y 5 >>== \z -> -- 12
undefined
GCHi> foo''
7
Woa! Возможно, мы только что придумали монаду cap10
!
Теперь, если мы посмотрим на исходный код Cont, мы видим, что Cont
есть
newtype Cont r a = Cont { runCont :: (a -> r) -> r }
Тип runCont
равен
Cont r a -> (a -> r) -> r
((a -> r) -> r) -> (a -> r) -> r
Какая линия хорошо сочетается с типом нашего >>==
Теперь, чтобы ответить на вопрос
Теперь, после ввода всего этого, я перечитываю исходный вопрос. ОП попросил "разницу": P
Я думаю, что разница заключается в том, что CPS дает больному больше контроля, где, как обычно, >>=
в монаде полностью контролируется автором монады.
Ответ 2
Возможно, вам стоит взглянуть на этот http://blog.sigfpe.com/2008/12/mother-of-all-monads.html
Ответ 3
Интересная статья, в которой рассматривается проблема, "Императивное функциональное программирование" , Пейтон Джонс и Вадлер.
Это документ, в который вводится монадический IO, и он имеет сравнение с альтернативными подходами, включая CPS.
Авторы заключают:
Итак, монады более мощные, чем продолжения, но только из-за типов! Неясно, является ли это всего лишь артефактом системы типа Хиндли-Милнера, или типы раскрывают разницу фундаментальной важности (наша собственная интуиция - последняя, но это только интуиция.)
Ответ 4
Нет никакого отношения, поэтому вопрос затрагивает столько же смысла, сколько и вопрос о различии между синим цветом и Плутоном.