可以在一个程序中向后跳到连续单点:
{-# 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 ()这不起作用,因为MonadFix (ContT r m)没有在Control.Monad.Trans.Cont中定义的连续monad转换器ContT的实例。有关详细信息,请参阅李恩康的论文的5.1节。
是否有一种方法可以对前跳进行编码,而不对连续单次进行值递归?
是否有一个具有ContT实例的MonadFix (ContT r m)的替代定义?马格努斯·卡尔松( Magnus )的未公布的草稿提出了这样的建议,但我不知道在我的情况下该怎么做。
发布于 2014-08-20 19:39:13
如果在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"这该怎么办?
您还可以稍后跳回跳过的代码。您只需要向跳过的代码传递一个延续。使用您的示例,可以将goto L2: L1: some code; goto END; L2: goto 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),返回到外部代码,以便它可以跳到那里。
https://stackoverflow.com/questions/25412238
复制相似问题