Fri Jan 18 09:09:04 EST 2008

```apfelmus wrote:
> Felipe Lessa wrote:
>> casePromptOf :: (r -> b)
>>              -> (forall a. p a -> (a -> b) -> b)
>>              -> Prompt p r -> b
>> casePromptOf done cont (PromptDone r) = done r
>> casePromptOf done cont (Prompt p c  ) = cont p (casePromptOf done cont . c)

[is just as general as]

>    casePromptOf' :: (r -> f c)
>                  -> (forall a,b. p a -> (a -> f b) -> f b)
>                  -> Prompt p r -> f c

That's nice.

So let's implement Prompt differently, using casePromptOf as a template:

> newtype Prompt p r = Prompt {
>     runP :: forall b . (r -> b) -> (forall a . p a -> (a -> b) -> b) -> b
> }

We can define a Monad instance easily enough:

> instance Monad (Prompt p) where
>     return a = Prompt \$ \done _   -> done a
>     f >>= g  = Prompt \$ \done prm -> runP f (\x -> runP (g x) done prm) prm

prompt can be implemented as follows:

> instance MonadPrompt (Prompt p) where
>     prompt p = \done prm -> prm p done

And finally define some handy functions for running it,

> runPromptC :: (r -> b) -> (forall a . p a -> (a -> b) -> b)
>            -> Prompt p r -> b
> runPromptC ret prm p = runP p ret prm

(runPromptC is just a different name for casePromptOf)

> runPromptM :: Monad m => (forall a . p a -> m a)
>            -> Prompt p r -> m r
> runPromptM prm = runPromptC return (\p cont -> prm p >>= cont)

The interesting point here is that by working with continuations, we
could eliminate the recursive call of (>>=) in its own implementation,
curing the quadratic slowdown for left associative uses of (>>=).

enjoy,

Bertram

P.S. I've written a small peg solitaire game using Prompt and gtk2hs,
available from