2015-08-16 2 views
0

После некоторого изучения ([1], [2], [3], среди прочих), я пытаюсь сделать работу монады продолжения, пытаясь привести некоторые примеры самостоятельно.Попытка осуществить с Cont монады. Синтаксическая проблема

Второй ответ [1] предлагает выразить факториал с использованием продолжений. Мое решение таково:

Cont ($ (fact 0)) = return 1 
Cont ($ (fact n)) = Cont ($ (fact (n-1))) >>= (\x -> Cont ($ (n*x))) 

Я сделал некоторые симуляции на бумаге, и решение должно быть правильным.

Однако Я не могу усвоить его GHC. Конечно, я переименовал функцию fact, но до сих пор не радуюсь.

Моя последняя попытка https://gist.github.com/Muzietto/595bef1815ddf375129d и дает как всегда parse error in pattern \c -> .....

Можно ли предложить бегущую реализацию этих определений?

[1] How and why does the Haskell Cont monad work?

[2] http://hackage.haskell.org/package/mtl-1.1.0.2/docs/Control-Monad-Cont.html

[3] https://wiki.haskell.org/MonadCont_under_the_hood

+0

первым: сущность прекрасно само по себе, но почему вы не скопировать и вставить код здесь - это просто удобно для нас пытается помочь здесь - Затем я не думаю, что ваши типы совпадают (или, я думаю, неправильно, что вы пытаетесь сделать) - попытались ли вы решить эту проблему только с продолжением-прохождением стиля (вам не нужна монада/'Cont' -wrapper, чтобы понять технику)? – Carsten

+0

@ carsten - Эта попытка моей действительно возникает из отлично работающей реализации CPS, определенно слишком тривиальной, чтобы упомянуть. Я считаю, что ясно, что весь смысл этого вопроса заключается в использовании монады, и особенно в ее функции связывания. –

ответ

4

Во-первых, вы не можете определить функцию в том, как вы публикуемую по той же причине вы не можете реализовать предшественник:

1 + (predecessor x) = x 

Функции могут определяться только уравнениями формы

f pattern1 .. patternK = expression 

Обратите внимание, что f должен быть найден на верхнем уровне.

Для вашей функции факториала, используя продолжение монада, вы можете упростить вашу попытку следующим образом:

fact :: Int -> Cont r Int 
-- Your own code: 
-- Cont ($ (fact 0)) = return 1 
fact 0 = return 1 
-- Cont ($ (fact n)) = Cont ($ (fact (n-1))) >>= (\x -> Cont ($ (n*x))) 
fact n = fact (n-1) >>= \x -> return (n*x) 

-- the "real" factorial function, without monads 
factorial :: Int -> Int 
factorial n = runCont (fact n) id 

Обратите внимание, что выше return (n*x) действительно Cont ($ (n*x)), но я думаю, что это более удобным для чтения в первом пути, а также из-за него не нарушает абстракции. Действительно, в будет работать любая монашка, написанная, как указано выше.

В качестве альтернативы, используйте do обозначение.

fact :: Int -> Cont r Int 
fact 0 = return 1 
fact n = do 
    x <- fact (n-1) 
    return (n*x) 

Или используйте оператор функтор:

fact :: Int -> Cont r Int 
fact 0 = return 1 
fact n = (n*) <$> fact (n-1) 
+0

Спасибо!Я подозревал, что в своем коде я делал что-то не-haskellian :-) Я увлекаюсь ощущением «привязки», надеясь привнести абстракцию на более высокий уровень. Я оценил тщательность и полноту вашего ответа. Функторная версия - умопомрачительная. Должен потратить некоторое время на размышление об этом fmap. –

+1

@ Мозаичные монады должны быть «совместимы» со своим экземпляром-функтором в том смысле, что они должны удовлетворять закону 'fmap f x = x >> = (return. F)'. В основном и неформально, если вы получаете что-то из монады ('>> ='), примените некоторую 'f', а затем верните ее в монаду с помощью' return', результат должен быть таким же, как и для fmap f. – chi

+0

Да, я знаю взаимосвязь между функторами и монадами, но я всегда считал, что 'bind' находится на более высоком уровне абстракции (и возможностей), чем' fmap'. Видение 'fmap' здесь делает более или менее одно и то же задание в синтаксисе четного синтаксиса. –

Смежные вопросы