module Control.Monad.Logic.Class (MonadLogic(..), reflect, lnot) where
import qualified Control.Monad.State.Lazy as LazyST
import qualified Control.Monad.State.Strict as StrictST
import Control.Monad.Reader
import Data.Monoid
import qualified Control.Monad.Writer.Lazy as LazyWT
import qualified Control.Monad.Writer.Strict as StrictWT
class (MonadPlus m) => MonadLogic m where
msplit :: m a -> m (Maybe (a, m a))
interleave :: m a -> m a -> m a
(>>-) :: m a -> (a -> m b) -> m b
infixl 1 >>-
ifte :: m a -> (a -> m b) -> m b -> m b
once :: m a -> m a
interleave m1 m2 = msplit m1 >>=
maybe m2 (\(a, m1') -> return a `mplus` interleave m2 m1')
m >>- f = do Just (a, m') <- 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 Just (a, _) <- msplit m
return a
reflect :: MonadLogic m => Maybe (a, m a) -> m a
reflect Nothing = mzero
reflect (Just (a, m)) = return a `mplus` m
lnot :: MonadLogic m => m a -> m ()
lnot m = ifte (once m) (const mzero) (return ())
instance MonadLogic [] where
msplit [] = return Nothing
msplit (x:xs) = return $ Just (x, xs)
instance MonadLogic m => MonadLogic (ReaderT e m) where
msplit rm = ReaderT $ \e -> do r <- msplit $ runReaderT rm e
case r of
Nothing -> return Nothing
Just (a, m) -> return (Just (a, lift m))
instance MonadLogic m => MonadLogic (StrictST.StateT s m) where
msplit sm = StrictST.StateT $ \s ->
do r <- msplit (StrictST.runStateT sm s)
case r of
Nothing -> return (Nothing, s)
Just ((a,s'), m) ->
return (Just (a, StrictST.StateT (\_ -> m)), s')
interleave ma mb = StrictST.StateT $ \s ->
StrictST.runStateT ma s `interleave` StrictST.runStateT mb s
ma >>- f = StrictST.StateT $ \s ->
StrictST.runStateT ma s >>- \(a,s') -> StrictST.runStateT (f a) s'
ifte t th el = StrictST.StateT $ \s -> ifte (StrictST.runStateT t s)
(\(a,s') -> StrictST.runStateT (th a) s')
(StrictST.runStateT el s)
once ma = StrictST.StateT $ \s -> once (StrictST.runStateT ma s)
instance MonadLogic m => MonadLogic (LazyST.StateT s m) where
msplit sm = LazyST.StateT $ \s ->
do r <- msplit (LazyST.runStateT sm s)
case r of
Nothing -> return (Nothing, s)
Just ((a,s'), m) ->
return (Just (a, LazyST.StateT (\_ -> m)), s')
interleave ma mb = LazyST.StateT $ \s ->
LazyST.runStateT ma s `interleave` LazyST.runStateT mb s
ma >>- f = LazyST.StateT $ \s ->
LazyST.runStateT ma s >>- \(a,s') -> LazyST.runStateT (f a) s'
ifte t th el = LazyST.StateT $ \s -> ifte (LazyST.runStateT t s)
(\(a,s') -> LazyST.runStateT (th a) s')
(LazyST.runStateT el s)
once ma = LazyST.StateT $ \s -> once (LazyST.runStateT ma s)
instance (MonadLogic m, Monoid w) => MonadLogic (StrictWT.WriterT w m) where
msplit wm = StrictWT.WriterT $
do r <- msplit (StrictWT.runWriterT wm)
case r of
Nothing -> return (Nothing, mempty)
Just ((a,w), m) ->
return (Just (a, StrictWT.WriterT m), w)
interleave ma mb = StrictWT.WriterT $
StrictWT.runWriterT ma `interleave` StrictWT.runWriterT mb
ma >>- f = StrictWT.WriterT $
StrictWT.runWriterT ma >>- \(a,w) ->
StrictWT.runWriterT (StrictWT.tell w >> f a)
ifte t th el = StrictWT.WriterT $
ifte (StrictWT.runWriterT t)
(\(a,w) -> StrictWT.runWriterT (StrictWT.tell w >> th a))
(StrictWT.runWriterT el)
once ma = StrictWT.WriterT $ once (StrictWT.runWriterT ma)
instance (MonadLogic m, Monoid w) => MonadLogic (LazyWT.WriterT w m) where
msplit wm = LazyWT.WriterT $
do r <- msplit (LazyWT.runWriterT wm)
case r of
Nothing -> return (Nothing, mempty)
Just ((a,w), m) ->
return (Just (a, LazyWT.WriterT m), w)
interleave ma mb = LazyWT.WriterT $
LazyWT.runWriterT ma `interleave` LazyWT.runWriterT mb
ma >>- f = LazyWT.WriterT $
LazyWT.runWriterT ma >>- \(a,w) ->
LazyWT.runWriterT (LazyWT.tell w >> f a)
ifte t th el = LazyWT.WriterT $
ifte (LazyWT.runWriterT t)
(\(a,w) -> LazyWT.runWriterT (LazyWT.tell w >> th a))
(LazyWT.runWriterT el)
once ma = LazyWT.WriterT $ once (LazyWT.runWriterT ma)