38 lines
1.4 KiB
Plaintext
38 lines
1.4 KiB
Plaintext
|
module Control.Monad.Logic.Class (class MonadLogic, msplit, interleave, fbind, reflect, (>>-)) where
|
||
|
|
||
|
import Prelude
|
||
|
|
||
|
import Control.MonadPlus (class MonadPlus, class Alternative, class Alt, class Plus, (<|>), empty)
|
||
|
import Control.Monad.Reader.Class (class MonadReader, local, class MonadAsk, ask)
|
||
|
import Control.Monad.State (runStateT)
|
||
|
import Control.Monad.State.Class (class MonadState, state)
|
||
|
import Control.Monad.State.Trans (StateT(..))
|
||
|
import Control.Monad.Trans.Class (class MonadTrans, lift)
|
||
|
import Data.Tuple.Nested (type (/\), (/\))
|
||
|
import Data.Maybe (Maybe(..))
|
||
|
|
||
|
class (MonadPlus m) <= MonadLogic m where
|
||
|
msplit :: forall a. m a -> m (Maybe (a /\ (m a)))
|
||
|
interleave :: forall a. m a -> m a -> m a
|
||
|
|
||
|
fbind :: forall a b m. MonadLogic m => m a -> (a -> m b) -> m b
|
||
|
fbind m f = do
|
||
|
r <- msplit m
|
||
|
case r of
|
||
|
Nothing -> empty
|
||
|
Just (a /\ m') -> interleave (f a) (m' `fbind` f)
|
||
|
|
||
|
reflect :: forall a m. MonadLogic m => Maybe (a /\ m a) -> m a
|
||
|
reflect Nothing = empty
|
||
|
reflect (Just (a /\ ma)) = pure a <|> ma
|
||
|
|
||
|
infixl 1 fbind as >>-
|
||
|
|
||
|
instance MonadLogic m => MonadLogic (StateT s m) where
|
||
|
msplit sm = StateT $ \s -> do
|
||
|
r <- msplit (runStateT sm s)
|
||
|
case r of
|
||
|
Nothing -> pure (Nothing /\ s)
|
||
|
Just ((a /\ s') /\ m) -> pure (Just (a /\ (StateT $ const m)) /\ s')
|
||
|
interleave m1 m2 = StateT $ \s -> runStateT m1 s <|> runStateT m2 s
|