Ответ 1
Вы можете сделать это, если вы переместите свой мертвый код внутри 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
) обратно во внешний код, чтобы он мог туда прыгать.