-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/

-- | MonadPrompt, implementation & examples
--   
--   "Prompting" monad that allows splitting the description of a
--   computation from the implementation of the effects used in that
--   computation.
--   http://www.haskell.org/pipermail/haskell-cafe/2008-January/038301.html
@package MonadPrompt
@version 1.0.0.5

-- | Implementation of monads that allow the computation to prompt
--   for further input.
--   
--   (c) 2008 Bertram Felgenhauer & Ryan Ingram Released as open source
--   under a 3 clause BSD license. See the LICENSE file in the source code
--   distribution for further information.
--   
--   RecPromptT added by Cale Gibbard, contributed under the same license.
--   
--   MonadPrompt monads allow you to pass some object of the prompt type
--   in, and get a result of the prompt's answer type out.
module Control.Monad.Prompt

-- | You can construct a monad very simply with prompt, by putting all of
--   its effects as terms in a GADT, like the following example:
--   
--   
--   data PromptState s a where
--       Put :: s -> PromptState s ()
--       Get :: PromptState s s
--   
--   
--   You then use prompt to access effects:
--   
--   
--   postIncrement :: MonadPrompt (PromptState Int) m => m Int
--   postIncrement =
--     do x <- prompt Get
--        prompt (Put (x+1))
--        return x
--   
--   
--   The advantage of Prompt over implementing effects directly:
--   
--   
--   
- Prompt is pure; it is only through the observation function
--   runPromptC that you can cause effects.
--   
- You don't have to worry about the monad laws; they are correct by
--   construction and you cannot break them.
--   
- You can implement several observation functions for the same type.
--   See, for example, http://paste.lisp.org/display/53766 where a
--   guessing game is implemented with an IO observation function for the
--   user, and an AI observation function that plays the game
--   automatically.
--   
--   
--   In these ways Prompt is similar to Unimo, but bind and return are
--   inlined into the computation, whereas in Unimo they are handled as a
--   term calculus. See
--   http://sneezy.cs.nott.ac.uk/fplunch/weblog/?p=89
class Monad m => MonadPrompt (p :: Type -> Type) (m :: Type -> Type) | m -> p
prompt :: MonadPrompt p m => p a -> m a
data Prompt (p :: Type -> Type) r

-- | runPromptC is the observation function for prompts. It takes
--   two functions as arguments:
--   
--   
--   
- ret will be called with the final result of the
--   computation, to convert it to the answer type.
--   
- prm will be called if there are any effects; it is passed
--   a prompt and a continuation function. prm can apply the effect
--   requested by the prompt and call the continuation.
--   
--   
--   In some cases prm can return the answer type directly; it may be
--   useful to abort the remainder of the computation, or save off the
--   continuation to be called later. There is a great example of using
--   this to implement a UI for peg solitaire in Bertram Felgenhauer's post
--   to Haskell-Cafe at
--   http://www.haskell.org/pipermail/haskell-cafe/2008-January/038301.html
runPromptC :: forall p r b. (r -> b) -> (forall a. () => p a -> (a -> b) -> b) -> Prompt p r -> b

-- | runPrompt takes a way of converting prompts to an element in a
--   pure fashion and calculates the result of the prompt
runPrompt :: (forall a. () => p a -> a) -> Prompt p r -> r

-- | runPromptM is similar to runPrompt but allows the
--   computation to happen in any monad.
runPromptM :: Monad m => (forall a. () => p a -> m a) -> Prompt p r -> m r

-- | RecPrompt is for prompts which are dependent on the prompt
--   monad.
--   
--   For example, a MonadPlus prompt:
--   
--   
--   data PromptPlus m a where
--     PromptZero :: PromptPlus m a
--     PromptPlus :: m a -> m a -> PromptPlus m a
--   
--   instance MonadPlus (RecPrompt PromptPlus) where
--     mzero = prompt PromptZero
--     mplus x y = prompt (PromptPlus x y)
--   
data RecPrompt (p :: Type -> Type -> Type -> Type) r
unRecPrompt :: RecPrompt p r -> Prompt (p (RecPrompt p)) r

-- | Runs a recursive prompt computation. This is similar to
--   runPromptC, but for recursive prompt types.
runRecPromptC :: forall p r b. (r -> b) -> (forall a. () => p (RecPrompt p) a -> (a -> b) -> b) -> RecPrompt p r -> b

-- | Run a recursive prompt computation in a pure fashion, similar to
--   runPrompt.
runRecPrompt :: (forall a. () => p (RecPrompt p) a -> a) -> RecPrompt p r -> r

-- | Run a recursive prompt computation in an arbitrary monad, similar to
--   runPromptM.
runRecPromptM :: Monad m => (forall a. () => p (RecPrompt p) a -> m a) -> RecPrompt p r -> m r

-- | Prompt can also be used to define monad transformers.
--   
--   You will notice the lack of a Monad m constraint; this is
--   allowed because Prompt doesn't use the underlying monad at all;
--   instead the observation function (generally implemented via
--   runPromptT) will have the constraint.
data PromptT (p :: Type -> Type) (m :: Type -> Type) a

-- | runPromptT runs a prompt monad transformer.
runPromptT :: forall p m r b. (r -> b) -> (forall a. () => p a -> (a -> b) -> b) -> (forall a. () => m a -> (a -> b) -> b) -> PromptT p m r -> b

-- | runPromptTM is a useful variant of runPromptT when interpreting
--   into another monad
runPromptTM :: forall p m r n. Monad n => (forall a. () => p a -> n a) -> (forall a. () => m a -> n a) -> PromptT p m r -> n r

-- | runPromptTM' specialises runPromptTM further for the case that
--   you're interpreting to the base monad by supplying the identity
--   function as the interpretation for lifted computations
runPromptTM' :: forall p m r. Monad m => (forall a. () => p a -> m a) -> PromptT p m r -> m r

-- | A higher-kinded Either, used in defining PromptT.
data Lift (p :: Type -> Type) (m :: Type -> Type) a
Effect :: p a -> Lift (p :: Type -> Type) (m :: Type -> Type) a
Lift :: m a -> Lift (p :: Type -> Type) (m :: Type -> Type) a
unPromptT :: PromptT p m a -> Prompt (Lift p m) a

-- | You can also lift any Prompt computation into a PromptT (or more
--   generally, any appropriate MonadPrompt instance). This is the kind of
--   place where the advantage of being able to use multiple observation
--   functions on Prompt really shows.
liftP :: forall (p :: Type -> Type) m r. MonadPrompt p m => Prompt p r -> m r

-- | A recursive variant of the prompt monad transformer.
data RecPromptT (p :: Type -> Type -> Type -> Type) (m :: Type -> Type) a
unRecPromptT :: RecPromptT p m a -> Prompt (Lift (p (RecPromptT p m)) m) a

-- | Run a recursive prompt monad transformer.
runRecPromptT :: forall p r b m. (r -> b) -> (forall a. () => p (RecPromptT p m) a -> (a -> b) -> b) -> (forall a. () => m a -> (a -> b) -> b) -> RecPromptT p m r -> b
instance GHC.Internal.Base.Applicative (Control.Monad.Prompt.Prompt p)
instance GHC.Internal.Base.Applicative (Control.Monad.Prompt.PromptT p m)
instance GHC.Internal.Base.Applicative (Control.Monad.Prompt.RecPrompt p)
instance GHC.Internal.Base.Applicative (Control.Monad.Prompt.RecPromptT p m)
instance GHC.Internal.Base.Functor (Control.Monad.Prompt.Prompt p)
instance GHC.Internal.Base.Functor (Control.Monad.Prompt.PromptT p m)
instance GHC.Internal.Base.Functor (Control.Monad.Prompt.RecPrompt p)
instance GHC.Internal.Base.Functor (Control.Monad.Prompt.RecPromptT p m)
instance Control.Monad.Prompt.MonadPrompt p (Control.Monad.Prompt.Prompt p)
instance Control.Monad.Prompt.MonadPrompt p (Control.Monad.Prompt.PromptT p m)
instance Control.Monad.Prompt.MonadPrompt (p (Control.Monad.Prompt.RecPrompt p)) (Control.Monad.Prompt.RecPrompt p)
instance Control.Monad.Prompt.MonadPrompt (p (Control.Monad.Prompt.RecPromptT p m)) (Control.Monad.Prompt.RecPromptT p m)
instance GHC.Internal.Base.Monad (Control.Monad.Prompt.Prompt p)
instance GHC.Internal.Base.Monad (Control.Monad.Prompt.PromptT p m)
instance GHC.Internal.Base.Monad (Control.Monad.Prompt.RecPrompt p)
instance GHC.Internal.Base.Monad (Control.Monad.Prompt.RecPromptT p m)
instance Control.Monad.Trans.Class.MonadTrans (Control.Monad.Prompt.PromptT p)
instance Control.Monad.Trans.Class.MonadTrans (Control.Monad.Prompt.RecPromptT p)
