首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用连续单跳

用连续单跳
EN

Stack Overflow用户
提问于 2014-08-20 18:47:43
回答 1查看 739关注 0票数 13

可以在一个程序中向后跳到连续单点:

代码语言:javascript
复制
{-# 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却不接受:

代码语言:javascript
复制
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 )的未公布的草稿提出了这样的建议,但我不知道在我的情况下该怎么做。

EN

回答 1

Stack Overflow用户

发布于 2014-08-20 19:39:13

如果在callCC中移动死代码,您可以这样做:

代码语言:javascript
复制
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

做你想做的事是不可能的。要了解原因,请考虑下面的示例:

代码语言:javascript
复制
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实现为:

代码语言:javascript
复制
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),返回到外部代码,以便它可以跳到那里。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25412238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档