Ztrategic-0.2.0: Language/Ztrategic.hs
{-# LANGUAGE Rank2Types, ScopedTypeVariables, FlexibleContexts, TypeApplications #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Use camelCase" #-}
module Language.Ztrategic where
import Language.ZipperAG
import Language.StrategicData
import Data.Generics.Zipper hiding (left, right, up, down')
import Data.Generics.Aliases
import Data.Maybe
import Data.Data
import Control.Monad -- (join, mplus, MonadPlus)
-- monad transformers, to extract the monad from adhocTP
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe
import Control.Monad.State.Lazy
import System.Random (randomRIO, initStdGen, setStdGen)
gatherChildren (trav, untrav) z = maybe [] ((navigation:) . gatherChildrenR navigation) $ down' z
where navigation = (fromJust . down' . trav, untrav . fromJust . up)
gatherChildrenR (toNthChild, fromNthChild) z = maybe [] ((navigation:) . gatherChildrenR navigation) $ right z
where navigation = (fromJust . right . toNthChild, fromNthChild)
breadthFirst_tdTP f = MkTP $ \z -> bf' f z [(id, id)]
where bf' f z [] = return z
bf' f z ((trav, untrav):travs) =
do
let thisNode = trav z
thisNodeTransformed <- applyTP f thisNode
let newTravs = gatherChildren (trav, untrav) thisNodeTransformed
baseTransformed = untrav thisNodeTransformed
bf' f baseTransformed (travs ++ newTravs)
----------
----
--- TP
----
----------
newtype TP m = MkTP (forall a. (Typeable a, StrategicData a) => Zipper a -> m (Zipper a))
unTP (MkTP f) = f
applyTP :: (Typeable a, StrategicData a) => TP m -> Zipper a -> m (Zipper a)
applyTP = unTP
full_tdTP :: (Monad m) => TP m -> TP m
full_tdTP f = f `seqTP` allTPdown (full_tdTP f) `seqTP` allTPright (full_tdTP f)
full_buTP :: (Monad m) => TP m -> TP m
full_buTP f = allTPright (full_buTP f) `seqTP` allTPdown (full_buTP f) `seqTP` f
once_tdTP :: (MonadPlus m) => TP m -> TP m
once_tdTP f = f `choiceTP` oneTPdown (once_tdTP f) `choiceTP` oneTPright (once_tdTP f)
once_buTP :: (MonadPlus m) => TP m -> TP m
once_buTP f = oneTPright (once_buTP f) `choiceTP` oneTPdown (once_buTP f) `choiceTP` f
--Experimental
stop_tdTP :: (MonadPlus m) => TP m -> TP m
stop_tdTP f = f `choiceTP` (allTPdown (stop_tdTP f) `seqTP` allTPright (stop_tdTP f))
--Experimental
stop_buTP :: (MonadPlus m) => TP m -> TP m
stop_buTP f = (allTPdown (stop_tdTP f) `seqTP` allTPright (stop_tdTP f)) `choiceTP` f
{-
New stuff
-}
atRoot :: Monad m => TP m -> TP m
atRoot tp = MkTP (\z -> moveM up (\v -> Just $ v.$ arity z) (applyTP tp z) (applyTP (atRoot tp)) z)
full_uptdTP :: (Monad m) => TP m -> TP m
full_uptdTP f = allTPup (full_uptdTP f) `seqTP` f
full_upbuTP :: (Monad m) => TP m -> TP m
full_upbuTP f = f `seqTP` allTPup (full_upbuTP f)
once_uptdTP :: (MonadPlus m) => TP m -> TP m
once_uptdTP f = oneTPup (once_upbuTP f) `choiceTP` f
once_upbuTP :: (MonadPlus m) => TP m -> TP m
once_upbuTP f = f `choiceTP` oneTPup (once_uptdTP f)
-- full_tdTPupwards :: forall m a. (Typeable a, Monad m) => Proxy a -> TP m -> TP m
-- full_tdTPupwards _ tp = MkTP $ \z ->
-- let (Just v) = (getHole @(Maybe a) z)
-- z' = trans forbid z
-- traversed = applyTP (atRoot (full_tdTP tp)) z'
-- in fmap (setHole v) traversed
-- counts a node if mutable
counter_func :: (Typeable a, MonadPlus m) => (a -> m a) -> a -> StateT Int m a
counter_func tr e = do
t <- lift $ tr e
modify succ
return e
-- counts the mutable nodes
counting :: (StrategicData a, Typeable n, MonadPlus m) =>
Zipper a -> (n -> m n) -> m Int
counting r tr = execStateT (applyTP (full_tdTP step) r) 0
where step = idTP `adhocTPSeq` counter_func tr
-- applies mutation if node is transformable and we are supposed to mutate now
mutation_func :: (MonadPlus m) => (a -> m a) -> a -> StateT Int m a
mutation_func tr e = do
--run the transformation to check for mzeros (which will end computations)
t <- lift $ tr e
modify pred
x <- get
if x==0
then return t
else return e
-- applies mutation_func with a random counter deciding when to actually mutate
mutating :: (StrategicData a, Typeable b, MonadPlus m) =>
Zipper a -> Int -> (b -> m b) -> m (Zipper a)
mutating r index tr = evalStateT (applyTP (full_tdTP step) r) index
where step = idTP `adhocTPSeq` mutation_func tr
once_RandomTP :: (Typeable n, StrategicData a) => Zipper a -> (n -> Maybe n) -> IO (Zipper a)
once_RandomTP r tr = do
let Just n = counting r tr
s <- initStdGen
setStdGen s
index <- randomRIO (1, n)
let Just v = mutating r index tr
return v
mutations :: (Data a, Typeable n, StrategicData a) =>
a -> (n -> Maybe n) -> [a]
mutations z tr = applyTU (full_tdTU step) $ toZipper z
where step = failTU `adhocTUZ` select tr
-- select :: (Typeable n, StrategicData a) =>
-- (n -> Maybe n) -> n -> Zipper a -> [a]
select tr node zipper = case tr node of
Nothing -> []
Just newNode -> let newZipper = setHole newNode zipper
in [fromZipper newZipper]
{-
/New stuff
-}
adhocTP :: (Monad m, Typeable b) => TP m -> (b -> m b) -> TP m
adhocTP f g = MkTP $ \z -> do
val <- elevate g z
maybe (applyTP f z) return val
adhocTPSeq :: (MonadPlus m, Typeable b) => TP m -> (b -> m b) -> TP m
adhocTPSeq f g = MkTP (\z -> do
val <- elevate g z
maybe (applyTP f z) (applyTP (tryTP f)) val)
`choiceTP` f
adhocTPZ :: (Monad m, Typeable a, Typeable b) => TP m -> (b -> Zipper a -> m b) -> TP m
adhocTPZ f g = MkTP $ \z -> do
val <- elevateZ g z
maybe (applyTP f z) return val
adhocTPZSeq :: (MonadPlus m, Typeable a, Typeable b) => TP m -> (b -> Zipper a -> m b) -> TP m
adhocTPZSeq f g = MkTP (\z -> do
val <- elevateZ g z
maybe (applyTP f z) (applyTP (tryTP f)) val)
`choiceTP` f
elevate :: (Monad m, Typeable b) => (b -> m b) -> Zipper a -> m (Maybe (Zipper a))
elevate g z = runMaybeT $ transM (MaybeT . maybe (return Nothing) (fmap cast . g) . cast) z
elevateZ :: (Monad m, Typeable a, Typeable b, Typeable c) => (b -> Zipper c -> m b) -> Zipper a -> m (Maybe (Zipper a))
elevateZ g z = runMaybeT $ transM (MaybeT . maybe (return Nothing) (\b -> maybe (return Nothing) (fmap cast . g b) (cast z)) . cast) z
--Identity function
idTP :: Monad m => TP m
idTP = MkTP return
--Failing function
failTP :: MonadPlus m => TP m
failTP = MkTP (const mzero)
allTPright :: (Monad m) => TP m -> TP m
allTPright f = MkTP $ \z -> moveM right left (return z) (applyTP f) z
allTPdown :: (Monad m) => TP m -> TP m
allTPdown f = MkTP $ \z -> moveM down' up (return z) (applyTP f) z
oneTPright :: (MonadPlus m) => TP m -> TP m
oneTPright f = MkTP $ moveM right left mzero (applyTP f)
oneTPdown :: (MonadPlus m) => TP m -> TP m
oneTPdown f = MkTP $ moveM down' up mzero (applyTP f)
--EXPERIMENTAL:
allTPleft :: (Monad m) => TP m -> TP m
allTPleft f = MkTP $ \z -> moveM left right (return z) (applyTP f) z
allTPup :: (Monad m) => TP m -> TP m
allTPup f = MkTP $ \z -> moveM up (\v -> Just $ v.$arity z) (return z) (applyTP f) z
-- (Just . flip (.$) (arity z))
oneTPleft :: (MonadPlus m) => TP m -> TP m
oneTPleft f = MkTP $ moveM left right mzero (applyTP f)
oneTPup :: (MonadPlus m) => TP m -> TP m
oneTPup f = MkTP $ \z -> moveM up (\v -> Just $ v.$arity z) mzero (applyTP f) z
--Sequential composition, ignores failure
seqTP :: Monad m => TP m -> TP m -> TP m
seqTP f g = MkTP (unTP f `mseq` unTP g)
f `mseq` g = f >=> g
--Sequential composition, chooses leftmost only if possible
choiceTP :: MonadPlus m => TP m -> TP m -> TP m
choiceTP f g = MkTP (unTP f `mchoice` unTP g)
f `mchoice` g = \x -> f x `mplus` g x
--Apply a function, fail the composition if it fails
monoTP :: (MonadPlus m, Typeable b) => (b -> m b) -> TP m
monoTP = adhocTP failTP
--Apply a function with access to the zipper, fail the composition if it fails
monoTPZ :: (MonadPlus m, Typeable a, Typeable b) => (b -> Zipper a -> m b) -> TP m
monoTPZ = adhocTPZ failTP
--Try to apply a zipper function, and apply identity if it fails
tryTP :: MonadPlus m => TP m -> TP m
tryTP s = s `choiceTP` idTP
repeatTP :: MonadPlus m => TP m -> TP m
repeatTP s = tryTP (s `seqTP` repeatTP s)
-- TODO Make sure that this innermost works for all cases?!
-- note that this is significantly faster than innermost'
innermost :: (MonadPlus m) => TP m -> TP m
innermost s = allTPright (innermost s)
`seqTP` allTPdown (innermost s)
`seqTP` tryTP (s `seqTP` innermost s)
innermost' :: (MonadPlus m) => TP m -> TP m
innermost' s = repeatTP (once_buTP s)
outermost :: (MonadPlus m) => TP m -> TP m
outermost s = repeatTP (once_tdTP s)
----------
----
--- TU
----
----------
newtype TU m d = MkTU (forall a. (Typeable a, StrategicData a) => Zipper a -> m d)
unTU (MkTU f) = f
applyTU :: (Typeable a, StrategicData a) => TU m d -> Zipper a -> m d
applyTU = unTU
foldr1TU :: (Monoid (m d), Foldable m, StrategicData a) => TU m d -> Zipper a -> (d -> d -> d) -> d
foldr1TU f z red = foldr1 red $ applyTU (full_tdTU f) z
foldl1TU :: (Monoid (m d), Foldable m, StrategicData a) => TU m d -> Zipper a -> (d -> d -> d) -> d
foldl1TU f z red = foldl1 red $ applyTU (full_tdTU f) z
foldrTU :: (Monoid (m d), Foldable m, StrategicData a) => TU m d -> Zipper a -> (d -> c -> c) -> c -> c
foldrTU f z red i = foldr red i $ applyTU (full_tdTU f) z
foldlTU :: (Monoid (m d), Foldable m, StrategicData a) => TU m d -> Zipper a -> (c -> d -> c) -> c -> c
foldlTU f z red i = foldl red i $ applyTU (full_tdTU f) z
full_tdTU :: Monoid (m d) => TU m d -> TU m d
full_tdTU f = f `seqTU` allTUdown (full_tdTU f) `seqTU` allTUright (full_tdTU f)
full_buTU :: Monoid (m d) => TU m d -> TU m d
full_buTU f = allTUright (full_buTU f) `seqTU` allTUdown (full_buTU f) `seqTU` f
once_tdTU :: (MonadPlus m, Monoid (m d)) => TU m d -> TU m d
once_tdTU f = f `choiceTU` allTUdown (once_tdTU f) `choiceTU` allTUright (once_tdTU f)
once_buTU :: (MonadPlus m, Monoid (m d)) => TU m d -> TU m d
once_buTU f = allTUright (once_buTU f) `choiceTU` allTUdown (once_buTU f) `choiceTU` f
--Experimental
stop_tdTU :: (MonadPlus m, Monoid (m d)) => TU m d -> TU m d
stop_tdTU f = f `choiceTU` (allTUdown (stop_tdTU f) `seqTU` allTUright (stop_tdTU f))
--Experimental
stop_buTU :: (MonadPlus m, Monoid (m d)) => TU m d -> TU m d
stop_buTU f = (allTUright (stop_buTU f) `seqTU` allTUdown (stop_buTU f)) `choiceTU` f
{-
New!
-}
full_uptdTU :: (MonadPlus m, Monoid (m d)) => TU m d -> TU m d
full_uptdTU f = allTUup (full_uptdTU f) `seqTU` f
full_upbuTU :: (MonadPlus m, Monoid (m d)) => TU m d -> TU m d
full_upbuTU f = f `seqTU` allTUup (full_upbuTU f)
once_uptdTU :: (MonadPlus m, Monoid (m d)) => TU m d -> TU m d
once_uptdTU f = allTUup (once_uptdTU f) `choiceTU` f
once_upbuTU :: (MonadPlus m, Monoid (m d)) => TU m d -> TU m d
once_upbuTU f = f `choiceTU` allTUup (once_upbuTU f)
allTUup :: Monoid (m d) => TU m d -> TU m d
allTUup f = MkTU $ \z -> moveQ up mempty (applyTU f) z
{-
/New!
-}
allTUdown :: Monoid (m d) => TU m d -> TU m d
allTUdown f = MkTU $ \z -> moveQ down' mempty (applyTU f) z
allTUright :: Monoid (m d) => TU m d -> TU m d
allTUright f = MkTU $ \z -> moveQ right mempty (applyTU f) z
adhocTU :: (Monad m, Typeable a) => TU m d -> (a -> m d) -> TU m d
adhocTU f g = MkTU $ \z -> fromMaybe (applyTU f z) (getHole z >>= return . g)
adhocTUZ :: (Monad m, Typeable a, Typeable c) => TU m d -> (a -> Zipper c -> m d) -> TU m d
adhocTUZ f g = MkTU $ \z -> fromMaybe (applyTU f z) (reduce g z)
reduce :: (Typeable a, Typeable c, Typeable e) => (a -> Zipper c -> m d) -> Zipper e -> Maybe (m d)
reduce f z = (\v -> fmap (f v) (cast z)) =<< getHole z
seqTU :: (Monoid (m d)) => TU m d-> TU m d -> TU m d
seqTU x y = MkTU $ \z -> applyTU x z `mappend` applyTU y z
choiceTU :: (MonadPlus m) => TU m d -> TU m d -> TU m d
choiceTU x y = MkTU $ \z -> applyTU x z `mplus` applyTU y z
failTU :: (MonadPlus m) => TU m d
failTU = MkTU (const mzero)
constTU :: Monad m => d -> TU m d
constTU d = MkTU (const . return $ d)
monoTU :: (MonadPlus m, Typeable a) => (a -> m d) -> TU m d
monoTU = adhocTU failTU
monoTUZ :: (MonadPlus m, Typeable a, Typeable e) => (a -> Zipper e -> m d) -> TU m d
monoTUZ = adhocTUZ failTU