Monadic Call/CC?
Ashley Yakeley
ashley@semantic.org
Thu, 21 Feb 2002 19:36:13 -0800
>Given this:
>
> class (Monad m) => PeirceMonad m where
> {
> peirceM :: ((a -> m b) -> m a) -> m a;
> };
>
>...which Monads can be made PeirceMonads?
Here's one:
data ContMonad p a = MkContMonad ((a -> p) -> p);
unContMonad (MkContMonad app) = app;
instance Monad (ContMonad p) where
{
return a = MkContMonad (\cont -> cont a);
(MkContMonad ma) >>= bf = MkContMonad (\cont -> ma (\a ->
unContMonad (bf a) cont));
};
instance PeirceMonad m where
{
peirceM foo = MkContMonad (\cont -> unContMonad (foo (\a ->
MkContMonad (\_ -> (cont a)))) cont);
};
doContMonad :: ContMonad p p -> p;
doContMonad cm = unContMonad cm id;
test1 = doContMonad (peirceM (\continuation -> do
{
continuation 1;
continuation 2;
continuation 3;
})); -- returns 1
Now here's the interesting thing. The usual way to represent "real-world"
functions (i.e. with side-effects, or changing the world) from a to b is
to define a special _type constructor_, 'IO', and define the function as
'a -> IO b'. But an alternative, would have been to define a special
_type_, Action, and define the function as 'a -> (b -> Action) ->
Action'. And then your 'main' function has type 'Action'.
Nor do we have to declare special >>= and return functions as we do for
IO.
Here's how it's equivalent:
type Action = IO ();
type ActionMonad = ContMonad Action;
doActionMonad :: ActionMonad () -> Action;
doActionMonad cm = unContMonad cm return;
liftIO :: IO a -> ActionMonad a;
liftIO ioa = MkContMonad (\cont -> ioa >>= cont);
...and note that we get Peirce continuations for free:
peirce foo cont = foo (\a _ -> (cont a)) cont; -- constructors removed
--
Ashley Yakeley, Seattle WA