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