Created
May 1, 2019 08:02
-
-
Save iamahuman/4486ee1e1bb418944dd72b7c7a3a4fe1 to your computer and use it in GitHub Desktop.
"setjmp / longjmp" in Haskell (continuations)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment