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


-- | A monad transformer for mocking mtl-style typeclasses
--   
--   This package provides a monad transformer that helps create “mocks” of
--   <tt>mtl</tt>-style typeclasses, intended for use in unit tests. A mock
--   can be executed by providing a sequence of expected monadic calls and
--   their results, and the mock will verify that the computation conforms
--   to the expectation.
--   
--   For more information, see the module documentation for
--   <a>Control.Monad.Mock</a>.
@package monad-mock
@version 0.2.0.0


-- | This module provides a monad transformer that helps create “mocks” of
--   <tt>mtl</tt>-style typeclasses, intended for use in unit tests. A mock
--   can be executed by providing a sequence of expected monadic calls and
--   their results, and the mock will verify that the computation conforms
--   to the expectation.
--   
--   For example, imagine a <tt>MonadFileSystem</tt> typeclass, which
--   describes a class of monads that may perform filesystem operations:
--   
--   <pre>
--   class <a>Monad</a> m =&gt; MonadFileSystem m where
--     readFile :: <a>FilePath</a> -&gt; m <a>String</a>
--     writeFile :: <a>FilePath</a> -&gt; <a>String</a> -&gt; m ()
--   </pre>
--   
--   Using <a>MockT</a>, it’s possible to test computations that use
--   <tt>MonadFileSystem</tt> in a completely pure way:
--   
--   <pre>
--   copyFile :: MonadFileSystem m =&gt; <a>FilePath</a> -&gt; <a>FilePath</a> -&gt; m ()
--   copyFile a b = do
--     x &lt;- readFile a
--     writeFile b x
--   
--   spec = describe "copyFile" <a>$</a>
--     it "reads a file and writes its contents to another file" <a>$</a>
--       <a>evaluate</a> <a>$</a> copyFile "foo.txt" "bar.txt"
--         <a>&amp;</a> <a>runMock</a> [ ReadFile "foo.txt" <a>:-&gt;</a> "contents"
--                   , WriteFile "bar.txt" "contents" <a>:-&gt;</a> () ]
--   </pre>
--   
--   To make the above code work, all you have to do is write a small GADT
--   that represents typeclass method calls and implement the <a>Action</a>
--   typeclass:
--   
--   <pre>
--   data FileSystemAction r where
--     ReadFile :: <a>FilePath</a> -&gt; FileSystemAction <a>String</a>
--     WriteFile :: <a>FilePath</a> -&gt; <a>String</a> -&gt; FileSystemAction ()
--   deriving instance <a>Eq</a> (FileSystemAction r)
--   deriving instance <a>Show</a> (FileSystemAction r)
--   
--   instance <a>Action</a> FileSystemAction where
--     <a>eqAction</a> (ReadFile a) (ReadFile b)
--       = if a <a>==</a> b then <a>Just</a> <a>Refl</a> else <a>Nothing</a>
--     <a>eqAction</a> (WriteFile a b) (WriteFile c d)
--       = if a <a>==</a> c &amp;&amp; b <a>==</a> d then <a>Just</a> <a>Refl</a> else <a>Nothing</a>
--     <a>eqAction</a> _ _ = <a>Nothing</a>
--   </pre>
--   
--   Then, just write a <tt>MonadFileSystem</tt> instance for <a>MockT</a>:
--   
--   <pre>
--   instance <a>Monad</a> m =&gt; MonadFileSystem (<a>MockT</a> FileSystemAction m) where
--     readFile a = <a>mockAction</a> "readFile" (ReadFile a)
--     writeFile a b = <a>mockAction</a> "writeFile" (WriteFile a b)
--   </pre>
--   
--   For some Template Haskell functions that eliminate the need to write
--   the above boilerplate, look at <a>makeAction</a> from
--   <a>Control.Monad.Mock.TH</a>.
module Control.Monad.Mock

-- | A monad transformer for creating mock instances of typeclasses. In
--   <tt><a>MockT</a> f m a</tt>, <tt>f</tt> should be an <a>Action</a>,
--   which should be a GADT that represents a reified version of typeclass
--   method calls.
data MockT f m a
type Mock f = MockT f Identity

-- | Runs a <a>MockT</a> computation given an expected list of calls and
--   results. If any method is called during the extent of the computation
--   that is unexpected, an exception will be thrown. Additionally, if the
--   computation terminates without making <i>all</i> of the expected
--   calls, an exception is raised.
runMockT :: forall f m a. (Action f, Monad m) => [WithResult f] -> MockT f m a -> m a
runMock :: forall f a. Action f => [WithResult f] -> Mock f a -> a

-- | Logs a method call within a mock.
mockAction :: (Action f, Monad m) => String -> f r -> MockT f m r

-- | A class of types that represent typeclass method calls. The type must
--   be of kind <tt>* -&gt; *</tt>, and its type parameter should represent
--   type of the method’s return type.
class Action f

-- | Compares two <a>Action</a>s for equality, and produces a witness of
--   type equality if the two actions are, in fact, equal.
eqAction :: Action f => f a -> f b -> Maybe (a :~: b)

-- | Converts an <a>Action</a> to a <a>String</a>, which will be used when
--   displaying mock failures.
--   
--   The default implementation of <a>showAction</a> just uses <a>Show</a>,
--   assuming there is an instance <tt>forall a. <a>Show</a> (f a)</tt>.
--   This instance can be derived by GHC using a standalone
--   <tt>deriving</tt> clause.
showAction :: Action f => f a -> String

-- | Converts an <a>Action</a> to a <a>String</a>, which will be used when
--   displaying mock failures.
--   
--   The default implementation of <a>showAction</a> just uses <a>Show</a>,
--   assuming there is an instance <tt>forall a. <a>Show</a> (f a)</tt>.
--   This instance can be derived by GHC using a standalone
--   <tt>deriving</tt> clause.
showAction :: (Action f, ForallF Show f) => f a -> String

-- | Represents both an expected call (an <a>Action</a>) and its expected
--   result.
data WithResult f
[:->] :: f r -> r -> WithResult f
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Control.Monad.Mock.MockT f m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Control.Monad.Mock.MockT f m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Control.Monad.Mock.MockT f m)
instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Control.Monad.Mock.MockT f m)
instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Control.Monad.Mock.MockT f m)
instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (Control.Monad.Mock.MockT f m)
instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Control.Monad.Mock.MockT f m)
instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Control.Monad.Mock.MockT f m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Monad.Mock.MockT f m)
instance Control.Monad.Trans.Class.MonadTrans (Control.Monad.Mock.MockT f)
instance GHC.Base.Monad m => GHC.Base.Monad (Control.Monad.Mock.MockT f m)
instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Monad.Mock.MockT f m)
instance GHC.Base.Functor m => GHC.Base.Functor (Control.Monad.Mock.MockT f m)
instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Control.Monad.Mock.MockT f m)
instance Control.Monad.Trans.Control.MonadTransControl (Control.Monad.Mock.MockT f)
instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Control.Monad.Mock.MockT f m)


-- | This module provides Template Haskell functions for automatically
--   generating types representing typeclass methods for use with
--   <a>Control.Monad.Mock</a>. The resulting datatypes can be used with
--   <a>runMock</a> or <a>runMockT</a> to mock out functionality in unit
--   tests.
--   
--   The primary interface to this module is the <a>makeAction</a>
--   function, which generates an action GADT given a list of mtl-style
--   typeclass constraints. For example, consider a typeclass that encodes
--   side-effectful monadic operations:
--   
--   <pre>
--   class <a>Monad</a> m =&gt; MonadFileSystem m where
--     readFile :: <a>FilePath</a> -&gt; m <a>String</a>
--     writeFile :: <a>FilePath</a> -&gt; <a>String</a> -&gt; m ()
--   </pre>
--   
--   The typeclass has an obvious, straightforward instance for <a>IO</a>.
--   However, one of the main value of using a typeclass is that a
--   alternate, pure instance may be provided for unit tests, which is what
--   <a>MockT</a> provides. Therefore, one might use <a>makeAction</a> to
--   automatically generate the necessary datatype and instances:
--   
--   <pre>
--   <a>makeAction</a> "FileSystemAction" [<a>ts</a>| MonadFileSystem |]
--   </pre>
--   
--   This generates three things:
--   
--   <ol>
--   <li>A <tt>FileSystemAction</tt> GADT with constructors that correspond
--   to the methods of <tt>MonadFileSystem</tt>.</li>
--   <li>An <a>Action</a> instance for <tt>FileSystemAction</tt>.</li>
--   <li>A <tt>MonadFileSystem</tt> instance for <tt><a>MockT</a>
--   FileSystemAction m</tt>.</li>
--   </ol>
--   
--   The generated code effectively looks like this:
--   
--   <pre>
--   data FileSystemAction r where
--     ReadFile :: <a>FilePath</a> -&gt; FileSystemAction <a>String</a>
--     WriteFile :: <a>FilePath</a> -&gt; <a>String</a> -&gt; FileSystemAction ()
--   deriving instance <a>Eq</a> (FileSystemAction r)
--   deriving instance <a>Show</a> (FileSystemAction r)
--   
--   instance <a>Action</a> FileSystemAction where
--     <a>eqAction</a> (ReadFile a) (ReadFile b)
--       = if a <a>==</a> b then <a>Just</a> <a>Refl</a> else <a>Nothing</a>
--     <a>eqAction</a> (WriteFile a b) (WriteFile c d)
--       = if a <a>==</a> c &amp;&amp; b <a>==</a> d then <a>Just</a> <a>Refl</a> else <a>Nothing</a>
--     <a>eqAction</a> _ _ = <a>Nothing</a>
--   
--   instance <a>Monad</a> m =&gt; MonadFileSystem (<a>MockT</a> FileSystemAction m) where
--     readFile a = <a>mockAction</a> "readFile" (ReadFile a)
--     writeFile a b = <a>mockAction</a> "writeFile" (WriteFile a b)
--   </pre>
--   
--   This can then be used in tandem with <a>runMock</a> to unit-test a
--   function that interacts with the file system in a completely pure way:
--   
--   <pre>
--   copyFile :: MonadFileSystem m =&gt; <a>FilePath</a> -&gt; <a>FilePath</a> -&gt; m ()
--   copyFile a b = do
--     x &lt;- readFile a
--     writeFile b x
--   
--   spec = describe "copyFile" <a>$</a>
--     it "reads a file and writes its contents to another file" <a>$</a>
--       <a>evaluate</a> <a>$</a> copyFile "foo.txt" "bar.txt"
--         <a>&amp;</a> <a>runMock</a> [ ReadFile "foo.txt" <tt>:-&gt;</tt> "contents"
--                   , WriteFile "bar.txt" "contents" <tt>:-&gt;</tt> () ]
--   </pre>
module Control.Monad.Mock.TH

-- | Given a list of monadic typeclass constraints of kind <tt>* -&gt;
--   <a>Constraint</a></tt>, generate a type with an <a>Action</a> instance
--   with constructors that have the same types as the methods.
--   
--   <pre>
--   class <a>Monad</a> m =&gt; MonadFileSystem m where
--     readFile :: <a>FilePath</a> -&gt; m <a>String</a>
--     writeFile :: <a>FilePath</a> -&gt; <a>String</a> -&gt; m ()
--   
--   <a>makeAction</a> <a>FileSystemAction</a> [<a>ts</a>| MonadFileSystem |]
--   </pre>
makeAction :: String -> Cxt -> Q [Dec]

-- | Given the name of a type of kind <tt>* -&gt; *</tt>, generate an
--   <a>Action</a> instance.
--   
--   <pre>
--   data FileSystemAction r where
--     ReadFile :: <a>FilePath</a> -&gt; FileSystemAction <a>String</a>
--     WriteFile :: <a>FilePath</a> -&gt; <a>String</a> -&gt; FileSystemAction ()
--   deriving instance <a>Eq</a> (FileSystemAction r)
--   deriving instance <a>Show</a> (FileSystemAction r)
--   
--   <a>deriveAction</a> ''FileSystemAction
--   </pre>
deriveAction :: Name -> Q [Dec]

-- | A quasi-quoter like the built-in <tt>[t| ... |]</tt> quasi-quoter, but
--   produces a <i>list</i> of types instead of a single type. Each type
--   should be separated by a comma.
--   
--   <pre>
--   &gt;&gt;&gt; [ts| Bool, (), String |]
--   [ConT GHC.Types.Bool,ConT GHC.Tuple.(),ConT GHC.Base.String]
--   
--   &gt;&gt;&gt; [ts| Maybe Int, Monad m |]
--   [AppT (ConT GHC.Base.Maybe) (ConT GHC.Types.Int),AppT (ConT GHC.Base.Monad) (VarT m)]
--   </pre>
ts :: QuasiQuoter
