尝试使用 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
首先,您不能按照您发布的方式定义函数,原因与您无法实现前置函数的原因相同:
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)
经过一些研究([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
首先,您不能按照您发布的方式定义函数,原因与您无法实现前置函数的原因相同:
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)