module ContLabel where import Control.Monad.Trans.Cont import Control.Monad.IO.Class type Jmp r m a = (Maybe a, Label r m a) newtype Label r m a = Label (Jmp r m a -> m r) setjmp :: ContT r m (Jmp r m a) setjmp = ContT $ \ c -> c (Nothing, Label c) longjmp :: Label r m a -> a -> ContT r m b longjmp l@(Label k) v = ContT $ \_ -> k (Just v, l) main :: IO () main = evalContT $ callCC $ \ k -> do let pr = liftIO . putStrLn (j, label_0) <- setjmp pr ("1st setjmp returned: " ++ show j) case j of Nothing -> pr "First invocation, continue" Just s -> do pr (show (s :: Int) ++ ". Goodbye, world!") k () (v, label_1) <- setjmp pr ("2nd setjmp returned: " ++ show (v :: Maybe String)) (let forever m = x where x = m *> x m0 = do liftIO $ putStr "Choose your next target (A/B): " sel <- liftIO $ getLine case sel of ('A':_) -> m' "Int" label_0 ('B':_) -> m' "String" label_1 _ -> pr "Nope" >> m0 m' tn label_x = forever $ do liftIO $ putStr ("Choose your " ++ tn ++ ": ") sel <- liftIO $ getLine case [ x | (x, "") <- reads sel ] of [x] -> longjmp label_x x [] -> pr "heck, no parse" _ -> pr "hell, ambiguous parse" in m0)