module Test.SmallCheck.Series.Utils
(
zipLogic
, zipLogic3
) where
import Control.Applicative (empty, (<|>))
import Control.Monad ((<=<))
import Control.Monad.Logic (MonadLogic(msplit))
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
zipLogic :: MonadLogic m => m a -> m b -> m (a, b)
zipLogic :: m a -> m b -> m (a, b)
zipLogic m a
gx m b
gy =
m (a, b) -> ((a, b) -> m (a, b)) -> Maybe (a, b) -> m (a, b)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m (a, b)
forall (f :: * -> *) a. Alternative f => f a
empty (a, b) -> m (a, b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (a, b) -> m (a, b))
-> (MaybeT m (a, b) -> m (Maybe (a, b)))
-> MaybeT m (a, b)
-> m (a, b)
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< MaybeT m (a, b) -> m (Maybe (a, b))
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT m (a, b) -> m (a, b)) -> MaybeT m (a, b) -> m (a, b)
forall a b. (a -> b) -> a -> b
$ do
(a
x, m a
rx) <- m (Maybe (a, m a)) -> MaybeT m (a, m a)
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m a -> m (Maybe (a, m a))
forall (m :: * -> *) a. MonadLogic m => m a -> m (Maybe (a, m a))
msplit m a
gx)
(b
y, m b
ry) <- m (Maybe (b, m b)) -> MaybeT m (b, m b)
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m b -> m (Maybe (b, m b))
forall (m :: * -> *) a. MonadLogic m => m a -> m (Maybe (a, m a))
msplit m b
gy)
m (a, b) -> MaybeT m (a, b)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (a, b) -> MaybeT m (a, b)) -> m (a, b) -> MaybeT m (a, b)
forall a b. (a -> b) -> a -> b
$ (a, b) -> m (a, b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
x, b
y) m (a, b) -> m (a, b) -> m (a, b)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m a -> m b -> m (a, b)
forall (m :: * -> *) a b. MonadLogic m => m a -> m b -> m (a, b)
zipLogic m a
rx m b
ry
zipLogic3 :: MonadLogic m => m a -> m b -> m c -> m (a, b, c)
zipLogic3 :: m a -> m b -> m c -> m (a, b, c)
zipLogic3 m a
gx m b
gy m c
gz =
m (a, b, c)
-> ((a, b, c) -> m (a, b, c)) -> Maybe (a, b, c) -> m (a, b, c)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m (a, b, c)
forall (f :: * -> *) a. Alternative f => f a
empty (a, b, c) -> m (a, b, c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (a, b, c) -> m (a, b, c))
-> (MaybeT m (a, b, c) -> m (Maybe (a, b, c)))
-> MaybeT m (a, b, c)
-> m (a, b, c)
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< MaybeT m (a, b, c) -> m (Maybe (a, b, c))
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT m (a, b, c) -> m (a, b, c))
-> MaybeT m (a, b, c) -> m (a, b, c)
forall a b. (a -> b) -> a -> b
$ do
(a
x, m a
rx) <- m (Maybe (a, m a)) -> MaybeT m (a, m a)
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m a -> m (Maybe (a, m a))
forall (m :: * -> *) a. MonadLogic m => m a -> m (Maybe (a, m a))
msplit m a
gx)
(b
y, m b
ry) <- m (Maybe (b, m b)) -> MaybeT m (b, m b)
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m b -> m (Maybe (b, m b))
forall (m :: * -> *) a. MonadLogic m => m a -> m (Maybe (a, m a))
msplit m b
gy)
(c
z, m c
rz) <- m (Maybe (c, m c)) -> MaybeT m (c, m c)
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m c -> m (Maybe (c, m c))
forall (m :: * -> *) a. MonadLogic m => m a -> m (Maybe (a, m a))
msplit m c
gz)
m (a, b, c) -> MaybeT m (a, b, c)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (a, b, c) -> MaybeT m (a, b, c))
-> m (a, b, c) -> MaybeT m (a, b, c)
forall a b. (a -> b) -> a -> b
$ (a, b, c) -> m (a, b, c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
x, b
y, c
z) m (a, b, c) -> m (a, b, c) -> m (a, b, c)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m a -> m b -> m c -> m (a, b, c)
forall (m :: * -> *) a b c.
MonadLogic m =>
m a -> m b -> m c -> m (a, b, c)
zipLogic3 m a
rx m b
ry m c
rz