[Haskell-beginners] Learning Monads with 'setjmp' and 'longjmp' like actions
Gesh
gesh at gesh.uni.cx
Wed Aug 31 03:03:46 UTC 2016
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-monads
[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
More information about the Beginners
mailing list