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


-- | A backtracking logic-programming monad.
--   
--   A continuation-based, backtracking, logic programming monad. An
--   adaptation of the two-continuation implementation found in the paper
--   "Backtracking, Interleaving, and Terminating Monad Transformers"
--   available here: <a>http://okmij.org/ftp/papers/LogicT.pdf</a>
@package logict
@version 0.6.0.2


-- | A backtracking, logic programming monad.
--   
--   Adapted from the paper /Backtracking, Interleaving, and Terminating
--   Monad Transformers/, by Oleg Kiselyov, Chung-chieh Shan, Daniel P.
--   Friedman, Amr Sabry
--   (<a>http://www.cs.rutgers.edu/~ccshan/logicprog/LogicT-icfp2005.pdf</a>)
module Control.Monad.Logic.Class

-- | Minimal implementation: msplit
class (MonadPlus m) => MonadLogic m where interleave m1 m2 = msplit m1 >>= maybe m2 (\ (a, m1') -> return a `mplus` interleave m2 m1') m >>- f = do { (a, m') <- maybe mzero return =<< msplit m; interleave (f a) (m' >>- f) } ifte t th el = msplit t >>= maybe el (\ (a, m) -> th a `mplus` (m >>= th)) once m = do { (a, _) <- maybe mzero return =<< msplit m; return a }

-- | Attempts to split the computation, giving access to the first result.
--   Satisfies the following laws:
--   
--   <pre>
--   msplit mzero                == return Nothing
--   msplit (return a `mplus` m) == return (Just (a, m))
--   </pre>
msplit :: MonadLogic m => m a -> m (Maybe (a, m a))

-- | Fair disjunction. It is possible for a logical computation to have an
--   infinite number of potential results, for instance:
--   
--   <pre>
--   odds = return 1 `mplus` liftM (2+) odds
--   </pre>
--   
--   Such computations can cause problems in some circumstances. Consider:
--   
--   <pre>
--   do x &lt;- odds `mplus` return 2
--      if even x then return x else mzero
--   </pre>
--   
--   Such a computation may never consider the 'return 2', and will
--   therefore never terminate. By contrast, interleave ensures fair
--   consideration of both branches of a disjunction
interleave :: MonadLogic m => m a -> m a -> m a

-- | Fair conjunction. Similarly to the previous function, consider the
--   distributivity law for MonadPlus:
--   
--   <pre>
--   (mplus a b) &gt;&gt;= k = (a &gt;&gt;= k) `mplus` (b &gt;&gt;= k)
--   </pre>
--   
--   If 'a &gt;&gt;= k' can backtrack arbitrarily many tmes, (b &gt;&gt;=
--   k) may never be considered. (&gt;&gt;-) takes similar care to consider
--   both branches of a disjunctive computation.
(>>-) :: MonadLogic m => m a -> (a -> m b) -> m b

-- | Logical conditional. The equivalent of Prolog's soft-cut. If its first
--   argument succeeds at all, then the results will be fed into the
--   success branch. Otherwise, the failure branch is taken. satisfies the
--   following laws:
--   
--   <pre>
--   ifte (return a) th el           == th a
--   ifte mzero th el                == el
--   ifte (return a `mplus` m) th el == th a `mplus` (m &gt;&gt;= th)
--   </pre>
ifte :: MonadLogic m => m a -> (a -> m b) -> m b -> m b

-- | Pruning. Selects one result out of many. Useful for when multiple
--   results of a computation will be equivalent, or should be treated as
--   such.
once :: MonadLogic m => m a -> m a

-- | The inverse of msplit. Satisfies the following law:
--   
--   <pre>
--   msplit m &gt;&gt;= reflect == m
--   </pre>
reflect :: MonadLogic m => Maybe (a, m a) -> m a

-- | Inverts a logic computation. If <tt>m</tt> succeeds with at least one
--   value, <tt>lnot m</tt> fails. If <tt>m</tt> fails, then <tt>lnot
--   m</tt> succeeds the value <tt>()</tt>.
lnot :: MonadLogic m => m a -> m ()
instance Control.Monad.Logic.Class.MonadLogic []
instance Control.Monad.Logic.Class.MonadLogic m => Control.Monad.Logic.Class.MonadLogic (Control.Monad.Trans.Reader.ReaderT e m)
instance Control.Monad.Logic.Class.MonadLogic m => Control.Monad.Logic.Class.MonadLogic (Control.Monad.Trans.State.Strict.StateT s m)
instance Control.Monad.Logic.Class.MonadLogic m => Control.Monad.Logic.Class.MonadLogic (Control.Monad.Trans.State.Lazy.StateT s m)
instance (Control.Monad.Logic.Class.MonadLogic m, GHC.Base.Monoid w) => Control.Monad.Logic.Class.MonadLogic (Control.Monad.Trans.Writer.Strict.WriterT w m)
instance (Control.Monad.Logic.Class.MonadLogic m, GHC.Base.Monoid w) => Control.Monad.Logic.Class.MonadLogic (Control.Monad.Trans.Writer.Lazy.WriterT w m)


-- | A backtracking, logic programming monad.
--   
--   Adapted from the paper /Backtracking, Interleaving, and Terminating
--   Monad Transformers/, by Oleg Kiselyov, Chung-chieh Shan, Daniel P.
--   Friedman, Amr Sabry
--   (<a>http://www.cs.rutgers.edu/~ccshan/logicprog/LogicT-icfp2005.pdf</a>).
module Control.Monad.Logic

-- | The basic Logic monad, for performing backtracking computations
--   returning values of type <tt>a</tt>
type Logic = LogicT Identity

-- | A smart constructor for Logic computations.
logic :: (forall r. (a -> r -> r) -> r -> r) -> Logic a

-- | Runs a Logic computation with the specified initial success and
--   failure continuations.
runLogic :: Logic a -> (a -> r -> r) -> r -> r

-- | Extracts the first result from a Logic computation.
observe :: Logic a -> a

-- | Extracts up to a given number of results from a Logic computation.
observeMany :: Int -> Logic a -> [a]

-- | Extracts all results from a Logic computation.
observeAll :: Logic a -> [a]

-- | A monad transformer for performing backtracking computations layered
--   over another monad <tt>m</tt>
newtype LogicT m a
LogicT :: (forall r. (a -> m r -> m r) -> m r -> m r) -> LogicT m a
[unLogicT] :: LogicT m a -> forall r. (a -> m r -> m r) -> m r -> m r

-- | Runs a LogicT computation with the specified initial success and
--   failure continuations.
runLogicT :: LogicT m a -> (a -> m r -> m r) -> m r -> m r

-- | Extracts the first result from a LogicT computation, failing
--   otherwise.
observeT :: Monad m => LogicT m a -> m a

-- | Extracts up to a given number of results from a LogicT computation.
observeManyT :: Monad m => Int -> LogicT m a -> m [a]

-- | Extracts all results from a LogicT computation.
observeAllT :: Monad m => LogicT m a -> m [a]
instance GHC.Base.Functor (Control.Monad.Logic.LogicT f)
instance GHC.Base.Applicative (Control.Monad.Logic.LogicT f)
instance GHC.Base.Alternative (Control.Monad.Logic.LogicT f)
instance GHC.Base.Monad (Control.Monad.Logic.LogicT m)
instance GHC.Base.MonadPlus (Control.Monad.Logic.LogicT m)
instance Control.Monad.Trans.Class.MonadTrans Control.Monad.Logic.LogicT
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Monad.Logic.LogicT m)
instance GHC.Base.Monad m => Control.Monad.Logic.Class.MonadLogic (Control.Monad.Logic.LogicT m)
instance (GHC.Base.Monad m, Data.Foldable.Foldable m) => Data.Foldable.Foldable (Control.Monad.Logic.LogicT m)
instance Data.Traversable.Traversable (Control.Monad.Logic.LogicT Data.Functor.Identity.Identity)
instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Control.Monad.Logic.LogicT m)
instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Control.Monad.Logic.LogicT m)
instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Control.Monad.Logic.LogicT m)
