尝试使用 Cont monad 进行锻炼。语法问题

Trying to exercise with the Cont monad. Syntax issue

经过一些研究([1]、[2]、[3] 等)后,我试图通过自己尝试一些示例来完成延续 monad。

[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

首先,您不能按照您发布的方式定义函数,原因与您无法实现前置函数的原因相同:

1 + (predecessor x) = x

函数只能通过以下形式的方程定义

f pattern1 .. patternK = expression

请注意,f 必须位于顶层。

对于使用延续 monad 的阶乘函数,您可以按如下方式简化您的尝试:

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)),但我认为前一种方式更具可读性,也因为它没有破坏抽象。事实上,一旦按上述方式编写,它就可以在 any monad 中工作。

或者,使用 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)