Learning Monads with 'setjmp' and 'longjmp' like actions

Hi, I'm really trying hard to understand monads but I guess my brain is trapped in the imperative world. Below what I have done so far. But now I would like to implement something like this: do foo (label, jumped) <- setjmp bar longjmp label But I'm stuck. How can I implement 'setjmp' and 'longjmp' with my monad? I'm not able to grasp how can I design 'setjmp' and somehow create a label to use in 'longjmp'. Maybe my monad structure is not appropriate? Code follows: --------------------------------------------------------------- data World = SomeWorld deriving (Eq, Show) data ProgramResult a = Result { world :: World, result :: a } | Continue { world :: World, continue :: Program a } | Stopped { world :: World } newtype Program a = Program { runProgram :: World -> ProgramResult a } runComplete :: Program a -> World -> (World, a) runComplete prg world0 = case runProgram prg world0 of (Result world1 x1) -> (world1, x1) (Continue world1 prg1) -> runComplete prg1 world1 nop :: Program () nop = return () yield :: Program () yield = Program $ \world -> Continue world nop stop :: Program () stop = Program $ \world -> Stopped world instance Functor Program where fmap = liftM instance Applicative Program where pure = return (<*>) = ap instance Monad Program where return x = Program $ \world0 -> Result world0 x ma >>= fb = Program $ \world0 -> case runProgram ma world0 of (Result world1 x1) -> runProgram (fb x1) world1 (Continue world1 prg1) -> Continue world1 (prg1 >>= fb) (Stopped world1) -> Stopped world1

On 2016-07-24 20:17, Michael Roth wrote:
Hi,
I'm really trying hard to understand monads but I guess my brain is trapped in the imperative world.
Below what I have done so far. But now I would like to implement something like this:
do foo (label, jumped) <- setjmp bar longjmp label
But I'm stuck. How can I implement 'setjmp' and 'longjmp' with my monad? I'm not able to grasp how can I design 'setjmp' and somehow create a label to use in 'longjmp'. Maybe my monad structure is not appropriate?
Code follows: ---------------------------------------------------------------
data World = SomeWorld deriving (Eq, Show)
data ProgramResult a = Result { world :: World, result :: a } | Continue { world :: World, continue :: Program a } | Stopped { world :: World } Firstly, you are correct in noting that `setjmp`/`longjmp` aren't implementable in your monad. Your monad is a variation on the following one: data Lazy a = Value a | Thunk (() -> Lazy a) with the obvious instances. In essence, given that your `World` type is opaque, I'm treating it as isomorphic to (). Given that, we have `ProgramResult a ~ Lazy (Maybe a)`.
In contrast, `setjmp`/`longjmp` are *much* more powerful than that. Any monad in which one can implement them can be used to implement `callCC`. One can embed the `Cont` monad into such monads (writing the code to do this is left as an exercise). However, one can embed any monad into `Cont`[0], from which it should be intuitively obvious that your monad is not up to the task. Moreover, usually `setjmp`/`longjmp` is not what you want. Derek Elkins explains this much better than I can[1], but in brief the problem with `setjmp` is that the continuation that it corresponds to contains its own use, which means you need to test whether the current execution of the code occurs before the first call to `longjmp`. The alternative he recommends is `callCC`, which is equivalent in power to `setjmp`/`longjmp` but whose usage is simpler. Hope this helps, despite the original question being over a month old. Gesh [0] - https://www.schoolofhaskell.com/school/advanced-haskell/the-mother-of-all-mo... [1] - http://lambda-the-ultimate.org/node/3611#comment-51086 P.S. An untested implementation of `setjmp`/`longjmp` in `Cont`:
throw :: r -> Cont r b throw e = Cont $ \_ -> e setjmp :: Cont r (Either (a -> Cont r b) a) setjmp = Cont $ \c-> c (Left (throw . c . Right)) longjmp :: (a -> Cont r b) -> a -> Cont r b longjmp c v = c v
participants (2)
-
Gesh
-
Michael Roth