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


-- | Record and replay the results of monadic actions
--   
--   A monad transformer and class that allows recording the results of
--   monadic actions and replay them later. Inspired by the logging
--   implementation in the transient package by Alberto G. Corona. Related
--   packages:
--   
--   <ul>
--   <li><a>https://hackage.haskell.org/package/transient</a></li>
--   <li><a>https://hackage.haskell.org/package/Workflow</a></li>
--   </ul>
@package monad-recorder
@version 0.1.1


-- | Results of the <a>RecorderT</a> computations are recorded in a running
--   journal using the <a>record</a> combinator. A computation can be
--   paused at any point using the <a>pause</a> primitive returning a
--   <a>Recording</a> that can be used to restart the computation from the
--   same point later. When the recording is replayed, the <a>record</a>
--   combinator returns the previously recorded result of the computation
--   from the journal instead of actually running the computation again.
--   
--   <pre>
--   import Control.Monad.IO.Class (liftIO)
--   import Control.Monad.Trans.Recorder (runRecorderT, record, pause, Paused(..), blank)
--   import Control.Exception (catch)
--   
--   main = do
--       recording &lt;- (runRecorderT blank computation &gt;&gt; return blank) `catch` \(Paused r) -&gt; return r
--       putStrLn "Computation paused, resuming again with recorded logs"
--       runRecorderT recording computation
--       return ()
--   
--       where
--   
--       computation = do
--            x1 &lt;- record $ liftIO $ return 1
--            record $ liftIO $ print ("A", x1)
--            x2 &lt;- record $ liftIO $ return 2
--            record pause
--            record $ liftIO $ print ("B", x1, x2)
--   </pre>
--   
--   Note that only those computations are replayed that are explicitly
--   recorded. Unrecorded impure computations can result in the program
--   misbehaving if it takes a different path upon replay. Instead of
--   recording selectively you can enforce recording of each and every
--   operation using the <tt>AutoRecorder</tt> module.
module Control.Monad.Trans.Recorder

-- | The monad record and play transformer. Maintains a running log of the
--   results of monadic actions.
data RecorderT m a

-- | The internal log state kept when recording or replaying.
data Journal

-- | A monad with the ability to record and play the results of monadic
--   actions.
class Monad m => MonadRecorder m

-- | Retrieve the record and replay journal. Used by the implementation of
--   <a>record</a> and <a>play</a>.
getJournal :: MonadRecorder m => m Journal

-- | Replace the record and replay journal. Used by the implementation of
--   <a>record</a> and <a>play</a>.
putJournal :: MonadRecorder m => Journal -> m ()

-- | Play a previously recorded journal. This function can be used to set a
--   replay journal at any point.
play :: MonadRecorder m => Recording -> m ()

-- | Run a fresh <a>RecorderT</a> computation using <a>blank</a> recording
--   or resume a paused computation using captured recording. The captured
--   state of the action is restored and the action resumes right after the
--   <a>pause</a> call that paused the action.
runRecorderT :: Monad m => Recording -> RecorderT m a -> m a

-- | A type that can be recorded.
class Recordable a
toJournal :: Recordable a => a -> String
fromJournal :: Recordable a => String -> a

-- | The log entries returned when an action is <tt>suspend</tt>ed.
data Recording

-- | An empty <a>Recording</a>.
blank :: Recording

-- | Add the result of an action to the recording journal. During replay,
--   if the result of an action is available in the replay journal then get
--   it from the journal instead of running the action.
record :: (Recordable a, Read a, Show a, MonadRecorder m) => m a -> m a

-- | Exception thrown when <a>pause</a> is called.
data Paused
Paused :: Recording -> Paused

-- | Pause a computation before completion for resuming later. Throws
--   <a>Paused</a> exception which carries the current recorded logs.
pause :: (MonadRecorder m, MonadThrow m) => m ()
instance GHC.Show.Show Control.Monad.Trans.Recorder.Paused
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Control.Monad.Trans.Recorder.RecorderT m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Control.Monad.Trans.Recorder.RecorderT m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Control.Monad.Trans.Recorder.RecorderT m)
instance Control.Monad.Trans.Class.MonadTrans Control.Monad.Trans.Recorder.RecorderT
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Monad.Trans.Recorder.RecorderT m)
instance GHC.Base.Monad m => GHC.Base.Monad (Control.Monad.Trans.Recorder.RecorderT m)
instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Monad.Trans.Recorder.RecorderT m)
instance GHC.Base.Functor m => GHC.Base.Functor (Control.Monad.Trans.Recorder.RecorderT m)
instance GHC.Show.Show Control.Monad.Trans.Recorder.Journal
instance GHC.Read.Read Control.Monad.Trans.Recorder.Journal
instance GHC.Show.Show Control.Monad.Trans.Recorder.Recording
instance GHC.Classes.Eq Control.Monad.Trans.Recorder.Recording
instance GHC.Show.Show Control.Monad.Trans.Recorder.LogEntry
instance GHC.Read.Read Control.Monad.Trans.Recorder.LogEntry
instance GHC.Classes.Eq Control.Monad.Trans.Recorder.LogEntry
instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Control.Monad.Trans.Recorder.RecorderT m)
instance GHC.Exception.Exception Control.Monad.Trans.Recorder.Paused
instance GHC.Base.Monad m => Control.Monad.Trans.Recorder.MonadRecorder (Control.Monad.Trans.Recorder.RecorderT m)
instance Control.Monad.Trans.Control.MonadTransControl Control.Monad.Trans.Recorder.RecorderT
instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Control.Monad.Trans.Recorder.RecorderT m)
instance (GHC.Show.Show a, GHC.Read.Read a) => Control.Monad.Trans.Recorder.Recordable a


-- | Unlike <a>RecorderT</a> which records selective operations using the
--   <a>record</a> combinator <a>AutoRecorderT</a> monad enforces recording
--   of all operations in the monad. This ensures that we do not miss
--   recording any monadic operation that could cause problems on replay.
--   
--   <pre>
--   import Control.Monad.IO.Class (liftIO)
--   import Control.Monad.Trans.Recorder (runRecorderT, record, pause, Paused(..), blank)
--   import Control.Monad.Trans.AutoRecorder (recorder, AutoRecorderT(R))
--   import Control.Exception (catch)
--   
--   main = do
--       recording &lt;- (runRecorderT blank computation &gt;&gt; return blank) `catch` \(Paused r) -&gt; return r
--       putStrLn "Computation paused, resuming again with recorded logs"
--       runRecorderT recording computation
--       return ()
--   
--       where
--   
--       computation = recorder $ do
--            x1 &lt;- R $ liftIO $ return 1
--            R $ liftIO $ print ("A", x1)
--            x2 &lt;- R $ liftIO $ return 2
--            R pause
--            R $ liftIO $ print ("B", x1, x2)
--   </pre>
module Control.Monad.Trans.AutoRecorder

-- | A monad that enforces recording of the results of all monadic actions.
--   The constructor <a>R</a> lifts a <a>MonadRecorder</a> monad to
--   <a>AutoRecorderT</a>.
data AutoRecorderT m a
[R] :: (MonadRecorder m, Show a, Read a) => m a -> AutoRecorderT m a

-- | Run the <a>AutoRecorderT</a> monad recording all operations in it.
recorder :: (MonadRecorder m, MonadThrow m, Show a, Read a) => AutoRecorderT m a -> m a
instance GHC.Base.Functor (Control.Monad.Trans.AutoRecorder.AutoRecorderT f)
instance GHC.Base.Applicative (Control.Monad.Trans.AutoRecorder.AutoRecorderT f)
instance GHC.Base.Monad (Control.Monad.Trans.AutoRecorder.AutoRecorderT m)
