продолжение прохождения стиль против монад - PullRequest
25 голосов
/ 24 декабря 2010

Чем отличаются стиль прохождения продолжения (cps) и монады.

Ответы [ 4 ]

24 голосов
/ 07 августа 2011

Как уже упоминалось в Сущность функционального программирования :

Программирование с помощью монад, сильно напоминающих стиль продолжения - прохождения (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:

Вот наша ванильная 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. Это похоже на выражение «вычисление Maybe должно остановиться и вернуть 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 "оборачивает" нормальное продолжение некоторой дополнительной логикой. И это очень близко к тому, что монада - склеить вычисления вместе с некоторой дополнительной логикой.

Давайте сделаем еще один шаг:

(>>==) :: ((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 дает вызывающему больше контроля, тогда как обычно >>= в монаде полностью контролируется ее автором.

7 голосов
/ 12 марта 2011

Возможно, вы захотите взглянуть на это http://blog.sigfpe.com/2008/12/mother-of-all-monads.html

4 голосов
/ 08 августа 2011

Интересная статья, которая исследует эту проблему, - "Императивное функциональное программирование" , Пейтон Джонс и Вадлер.

Это документ, который ввел монадический ввод-вывод, и в нем есть сравнение с альтернативными подходами, включая CPS.

Авторы делают вывод:

Таким образом, монады более мощные, чем продолжения, но только из-за типов!Не ясно, является ли это только артефактом системы типов Хиндли-Милнера, или типы обнаруживают разницу фундаментального значения (наша собственная интуиция - последняя, ​​но это только интуиция).

0 голосов
/ 24 декабря 2010

Нет никакой связи, поэтому вопрос имеет такой же смысл, как вопрос о разнице между синим цветом и Плутоном.

...