簡體   English   中英

繼續使用延續monad

[英]Jumping forward with the continuation monad

可以使用continuation 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 rm)實例。 有關詳細信息,請參閱Levent Erkok論文的第5.1節。

有沒有一種方法來編碼前向跳轉而沒有值繼續monad的值遞歸?

是否存在具有ContT實例MonadFix (ContT rm)ContT的替代定義? 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"

這應該怎么辦?


您也可以稍后跳回到跳過的代碼。 您只需將延續傳遞給您跳過的代碼即可。 使用您的示例, goto L2: L1: some code; goto END; L2: goto L1; END: return goto L2: L1: some code; goto END; L2: goto L1; END: return 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 )回到外部代碼,以便它可以跳轉到那里。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM