module Common.LogicT (
  LogicT (..), bagofN, reflect
) where
import Control.Monad
import Control.Monad.Trans
class MonadTrans t => LogicT t where
    msplit :: (Monad m, MonadPlus (t m)) => t m a -> t m (Maybe (a, t m a))
    
    
    interleave :: (Monad m, MonadPlus (t m)) =>
                  t m a -> t m a -> t m a
    
    interleave sg1 :: t m a
sg1 sg2 :: t m a
sg2 =
        do Maybe (a, t m a)
r <- t m a -> t m (Maybe (a, t m a))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(LogicT t, Monad m, MonadPlus (t m)) =>
t m a -> t m (Maybe (a, t m a))
msplit t m a
sg1
           case Maybe (a, t m a)
r of
                  Nothing -> t m a
sg2
                  Just (sg11 :: a
sg11, sg12 :: t m a
sg12) -> a -> t m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
sg11 t m a -> t m a -> t m a
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` t m a -> t m a -> t m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(LogicT t, Monad m, MonadPlus (t m)) =>
t m a -> t m a -> t m a
interleave t m a
sg2 t m a
sg12
    
    gsuccess :: (Monad m, MonadPlus (t m)) => a -> t m a
    gsuccess = a -> t m a
forall (m :: * -> *) a. Monad m => a -> m a
return
    gfail :: (Monad m, MonadPlus (t m)) => t m a
    gfail = t m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
    
    bindi :: (Monad m, MonadPlus (t m)) =>
            t m a -> (a -> t m b) -> t m b
    bindi sg :: t m a
sg g :: a -> t m b
g = do Maybe (a, t m a)
r <- t m a -> t m (Maybe (a, t m a))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(LogicT t, Monad m, MonadPlus (t m)) =>
t m a -> t m (Maybe (a, t m a))
msplit t m a
sg
                    case Maybe (a, t m a)
r of
                       Nothing -> t m b
forall (m :: * -> *) a. MonadPlus m => m a
mzero
                       Just (sg1 :: a
sg1, sg2 :: t m a
sg2) -> t m b -> t m b -> t m b
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(LogicT t, Monad m, MonadPlus (t m)) =>
t m a -> t m a -> t m a
interleave
                                            (a -> t m b
g a
sg1)
                                            (t m a -> (a -> t m b) -> t m b
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a b.
(LogicT t, Monad m, MonadPlus (t m)) =>
t m a -> (a -> t m b) -> t m b
bindi t m a
sg2 a -> t m b
g)
    
    
    ifte :: (Monad m, MonadPlus (t m)) =>
            t m a -> (a -> t m b) -> t m b -> t m b
    ifte t :: t m a
t th :: a -> t m b
th el :: t m b
el =
        do Maybe (a, t m a)
r <- t m a -> t m (Maybe (a, t m a))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(LogicT t, Monad m, MonadPlus (t m)) =>
t m a -> t m (Maybe (a, t m a))
msplit t m a
t
           case Maybe (a, t m a)
r of
                  Nothing -> t m b
el
                  Just (sg1 :: a
sg1, sg2 :: t m a
sg2) -> a -> t m b
th a
sg1 t m b -> t m b -> t m b
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` (t m a
sg2 t m a -> (a -> t m b) -> t m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> t m b
th)
    once :: (Monad m, MonadPlus (t m)) => t m a -> t m a
    once m :: t m a
m =
        do Maybe (a, t m a)
r <- t m a -> t m (Maybe (a, t m a))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(LogicT t, Monad m, MonadPlus (t m)) =>
t m a -> t m (Maybe (a, t m a))
msplit t m a
m
           case Maybe (a, t m a)
r of
                  Nothing -> t m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
                  Just (sg1 :: a
sg1, _) -> a -> t m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
sg1
    
bagofN :: (Monad m, LogicT t, MonadPlus (t m)) => Maybe Int -> t m a -> t m [a]
bagofN :: Maybe Int -> t m a -> t m [a]
bagofN (Just n :: Int
n) _ | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 = [a] -> t m [a]
forall (m :: * -> *) a. Monad m => a -> m a
return []
bagofN n :: Maybe Int
n m :: t m a
m = t m a -> t m (Maybe (a, t m a))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(LogicT t, Monad m, MonadPlus (t m)) =>
t m a -> t m (Maybe (a, t m a))
msplit t m a
m t m (Maybe (a, t m a)) -> (Maybe (a, t m a) -> t m [a]) -> t m [a]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (a, t m a) -> t m [a]
forall (m :: * -> *) (t :: (* -> *) -> * -> *) a.
(Monad m, LogicT t, MonadPlus (t m)) =>
Maybe (a, t m a) -> t m [a]
bagofN'
    where bagofN' :: Maybe (a, t m a) -> t m [a]
bagofN' Nothing = [a] -> t m [a]
forall (m :: * -> *) a. Monad m => a -> m a
return []
          bagofN' (Just (a :: a
a, m' :: t m a
m')) = ([a] -> [a]) -> t m [a] -> t m [a]
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
:) (t m [a] -> t m [a]) -> t m [a] -> t m [a]
forall a b. (a -> b) -> a -> b
$ Maybe Int -> t m a -> t m [a]
forall (m :: * -> *) (t :: (* -> *) -> * -> *) a.
(Monad m, LogicT t, MonadPlus (t m)) =>
Maybe Int -> t m a -> t m [a]
bagofN ((Int -> Int) -> Maybe Int -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((-1) Int -> Int -> Int
forall a. Num a => a -> a -> a
+) Maybe Int
n) t m a
m'
    
reflect :: (Monad m, LogicT t, MonadPlus (t m)) => Maybe (a, t m a) -> t m a
reflect :: Maybe (a, t m a) -> t m a
reflect r :: Maybe (a, t m a)
r = case Maybe (a, t m a)
r of
                   Nothing -> t m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
                   Just (a :: a
a, tmr :: t m a
tmr) -> a -> t m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a t m a -> t m a -> t m a
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` t m a
tmr