gpt4 book ai didi

haskell - 用延续单子(monad)向前跳跃

转载 作者:行者123 更新时间:2023-12-02 07:24:09 25 4
gpt4 key购买 nike

可以使用延续 monad 在程序中向后跳转:

{-# LANGUAGE RecursiveDo #-}

import Control.Monad.Fix
import Control.Monad.Trans.Cont

setjmp = callCC (\c -> return (fix c))

backward = do
l <- setjmp
-- some code to be repeated forever
l

但是当我尝试向前跳转时,GHC 不接受:

forward = mdo
l
-- some dead code
l <- setjmp
return ()

这不起作用,因为 Control.Monad.Trans.Cont 中定义的延续 monad 转换器 ContT 没有 MonadFix (ContT r m) 实例。请参阅 Levent Erkok's thesis 的第 5.1 节了解更多详情。

有没有一种方法可以在没有值递归的情况下对延续单子(monad)进行前向跳转编码?

是否有 ContT 的替代定义,其中包含 MonadFix (ContT r m) 的实例?有一个unpublished draft Magnus Carlsson 提出了这样的建议,但我不知道在我的情况下该怎么做。

最佳答案

如果将死代码移到 callCC 内,就可以做到这一点,如下所示:

import Control.Monad.Cont

forward :: ContT () IO ()
forward = do
callCC $ \skip -> do
skip ()
lift $ putStrLn "This is not executed"
lift $ putStrLn "Control flow continues here"

main :: IO ()
main = runContT forward return

不可能完全按照你的意愿去做。要了解原因,请考虑以下示例:

mdo
l
c <- lift getChar
l <- if c == 'a' then setjmp else return (return ())
lift $ putStrLn "end"

这应该做什么?

<小时/>

您还可以稍后跳回到被跳过的代码。您只需要将继续传递到您跳过的代码即可。使用您的示例,转到 L2: L1: 一些代码;转到结束; L2:转到L1; END: return 可以实现为:

import Control.Monad.Cont

forward :: ContT () IO ()
forward = do
callCC $ \end -> do
l1 <- callCC $ \l2 -> do
callCC $ \l1 -> l2 l1
liftIO $ putStrLn "In L1"
end ()
liftIO $ putStrLn "In L2"
l1 ()
liftIO $ putStrLn "End"

main :: IO ()
main = runContT forward return

在这里,我们将跳过的部分 (l1) 的延续传递回外部代码,以便它可以跳转到那里。

关于haskell - 用延续单子(monad)向前跳跃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25412238/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com