module Data.Generics.Strafunski.StrategyLib.Models.Deriving.StrategyPrimitives (
Term,
TP, TU,
paraTP, paraTU,
applyTP, applyTU,
adhocTP, adhocTU,
msubstTP, msubstTU,
seqTP, seqTU,
passTP, passTU,
choiceTP, choiceTU,
mchoicesTP, mchoicesTU,
allTP, allTU, allTU',
oneTP, oneTU,
anyTP, anyTU, anyTU',
someTP, someTU, someTU',
injTP
) where
import Data.Generics.Strafunski.StrategyLib.Models.Deriving.TermRep
import Data.Generics
import Control.Monad
import Data.Monoid
import Data.Generics.Strafunski.StrategyLib.MonadicFunctions
import Control.Monad.Run
newtype Monad m =>
TP m =
MkTP (forall x. Data x => x -> m x)
newtype Monad m =>
TU a m =
MkTU (forall x. Data x => x -> m a)
unTP (MkTP f) = f
unTU (MkTU f) = f
paraTP :: Monad m => (forall t. t -> m t) -> TP m
paraTP f = MkTP f
paraTU :: Monad m => (forall t. t -> m a) -> TU a m
paraTU f = MkTU f
applyTP :: (Monad m, Data x) => TP m -> x -> m x
applyTP = unTP
applyTU :: (Monad m, Data x) => TU a m -> x -> m a
applyTU = unTU
adhocTP :: (Monad m, Data t) => TP m -> (t -> m t) -> TP m
adhocTP s f = MkTP (unTP s `extM` f)
adhocTU :: (Monad m, Data t) => TU a m -> (t -> m a) -> TU a m
adhocTU s f = MkTU (unTU s `extQ` f)
msubstTP :: (Monad m, Monad m')
=> (forall t . m t -> m' t) -> TP m -> TP m'
msubstTP e f = MkTP (\x -> e ((unTP f) x))
msubstTU :: (Monad m, Monad m')
=> (m a -> m' a) -> TU a m -> TU a m'
msubstTU e f = MkTU (\x -> e ((unTU f) x))
seqTP :: Monad m => TP m -> TP m -> TP m
seqTP f g = MkTP ((unTP f) `mseq` (unTP g))
passTP :: Monad m => TU a m -> (a -> TP m) -> TP m
passTP f g = MkTP ((unTU f) `mlet` (\y -> unTP (g y)))
seqTU :: Monad m => TP m -> TU a m -> TU a m
seqTU f g = MkTU ((unTP f) `mseq` (unTU g))
passTU :: Monad m => TU a m -> (a -> TU b m) -> TU b m
passTU f g = MkTU ((unTU f) `mlet` (\y -> unTU (g y)))
choiceTP :: MonadPlus m => TP m -> TP m -> TP m
choiceTP f g = MkTP ((unTP f) `mchoice` (unTP g))
choiceTU :: MonadPlus m => TU a m -> TU a m -> TU a m
choiceTU f g = MkTU ((unTU f) `mchoice` (unTU g))
mchoicesTP fs f = MkTP (\a -> mchoices (map unTP fs) (unTP f) a)
mchoicesTU fs f = MkTU (\a -> mchoices (map unTU fs) (unTU f) a)
allTP :: Monad m => TP m -> TP m
allTP s = MkTP (gmapM (applyTP s))
oneTP :: MonadPlus m => TP m -> TP m
oneTP s = MkTP (gmapMo (applyTP s))
anyTP :: MonadPlus m => TP m -> TP m
anyTP s = allTP (s `choiceTP` paraTP return)
someTP :: MonadPlus m => TP m -> TP m
someTP s = MkTP (gmapMp (applyTP s))
injTP :: MonadPlus m => TP m -> TP m
injTP s = (MkTU (return . glength))
`passTP`
(\x -> if x == 1 then allTP s else paraTP (const mzero))
allTU :: Monad m => (a -> a -> a) -> a -> TU a m -> TU a m
allTU op2 u s = MkTU (\x -> fold (gmapQ (applyTU s) x))
where
fold l = foldM op2' u l
op2' x c = c >>= \y -> return (x `op2` y)
allTU' :: (Monad m, Monoid a) => TU a m -> TU a m
allTU' = allTU mappend mempty
oneTU :: MonadPlus m => TU a m -> TU a m
oneTU s = MkTU (\x -> fold (gmapQ (applyTU s) x))
where
fold [] = mzero
fold (h:t) = (h >>= \x -> return x)
`mplus`
fold t
anyTU :: MonadPlus m => (a -> a -> a) -> a -> TU a m -> TU a m
anyTU op2 u s = allTU op2 u (s `choiceTU` paraTU (const (return u)))
anyTU' :: (MonadPlus m, Monoid a) => TU a m -> TU a m
anyTU' = anyTU mappend mempty
someTU :: MonadPlus m => (a -> a -> a) -> a -> TU a m -> TU a m
someTU op2 u s = MkTU (\x -> fold False (gmapQ (applyTU s) x))
where
fold False [] = mzero
fold True [] = return u
fold b (h:t) = (h >>= \x -> fold True t >>= \y -> return (x `op2` y))
`mplus`
fold b t
someTU' :: (Monoid a, MonadPlus m) => TU a m -> TU a m
someTU' = someTU mappend mempty