packages feed

Ztrategic-0.2.0: Language/Memo/Safe/Ztrategic.hs

{-# LANGUAGE Rank2Types,DeriveDataTypeable #-}
module Language.Memo.Safe.Ztrategic where

import Language.ZipperAG
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)

import Language.StrategicData
import Language.Memo.Safe.AGMemo

----------
----
--- TP
----
----------

type TP a = Zipper a -> Maybe (Zipper a)

applyTP :: TP (d m) -> Zipper (d m) -> Maybe (Zipper (d m))
applyTP f z = f z

full_tdTP :: StrategicData (d m) => TP (d m) -> TP (d m) 
full_tdTP f = allTPdown (full_tdTP f) `seqTP` allTPright (full_tdTP f) `seqTP` f 

full_buTP :: StrategicData (d m) => TP (d m) -> TP (d m) 
full_buTP f = f `seqTP` allTPright (full_buTP f) `seqTP` allTPdown (full_buTP f) 

once_tdTP :: StrategicData (d m) => TP (d m) -> TP (d m) 
once_tdTP f =  oneTPdown (once_tdTP f) `choiceTP` oneTPright (once_tdTP f) `choiceTP` f

once_buTP :: StrategicData (d m) => TP (d m) -> TP (d m)   
once_buTP f = f `choiceTP` oneTPright (once_buTP f) `choiceTP` oneTPdown (once_buTP f) 

--https://hackage.haskell.org/package/ZipperAG-0.9/docs/Language-Grammars-ZipperAG-Examples-Algol68.html
--change use to decl

--Experimental
stop_tdTP :: StrategicData (d m) => TP (d m) -> TP (d m)   
stop_tdTP f = oneTPdown (stop_tdTP f) `choiceTP` f `seqTP` oneTPright (stop_tdTP f)

--Experimental
stop_buTP :: StrategicData (d m) => TP (d m) -> TP (d m)   
stop_buTP f = oneTPright (stop_buTP f) `seqTP` (f  `choiceTP` oneTPdown (stop_buTP f))

adhocTP :: Typeable a => TP (d m) -> (a -> Maybe a) -> TP (d m)
adhocTP f g = maybeKeep f (zTryApplyM g) 

adhocTPZ :: Typeable a => TP (d m) -> (a -> Zipper (d m) -> Maybe (Zipper (d m))) -> TP (d m)
adhocTPZ f g = maybeKeep f (zTryApplyMZ g)

--Identity function
idTP :: TP (d m)
idTP a = return a

idTP_invalidateDep :: Memoizable d m => TP (d m)
idTP_invalidateDep a = return $ invalidateDependencies a

--Failing function
failTP :: TP (d m) 
failTP = const mzero



maybeKeep :: (a -> Maybe a) -> (a -> Maybe a) -> a -> Maybe a
maybeKeep x y z =  case y z of 
              Nothing -> x z 
              Just r -> case x r of 
                  Nothing ->  Just r
                  k -> k 

allTPright :: StrategicData (d m) => TP (d m) -> TP (d m) 
allTPright f z = case right z of 
         Nothing -> return z
         Just r  -> (fromJust . left) <$> f r

--To down node only
allTPdown :: StrategicData (d m) => TP (d m) -> TP (d m)
allTPdown f z = case down' z of 
            Nothing -> return z
            Just d  -> (fromJust . up) <$> f d

--To right node only
oneTPright :: StrategicData (d m) => TP (d m) -> TP (d m)
oneTPright f z = case right z of 
         Nothing -> Nothing
         Just r  -> (fromJust . left) <$> f r

--To down node only
oneTPdown :: StrategicData (d m) => TP (d m) -> TP (d m)
oneTPdown f z = case down' z of 
            Nothing -> Nothing
            Just d  -> (fromJust . up) <$> f d  

--Sequential composition, ignores failure
seqTP :: TP (d m) -> TP (d m) -> TP (d m)
seqTP x y z = maybeKeep x y z
f `mseq` g      =  \x -> g x >>= f

--Sequential composition, chooses rightmost only if possible
choiceTP :: TP (d m) -> TP (d m) -> TP (d m)
choiceTP x y z = maybe (x z) (return . id) (y z)

--Apply a function, fail the composition if it fails
monoTP :: Typeable a => (a -> Maybe a) -> TP (d m)
monoTP = adhocTP failTP

--Apply a function with access to the zipper, fail the composition if it fails
monoTPZ :: Typeable a => (a -> Zipper (d m) -> Maybe (Zipper (d m))) -> TP (d m)
monoTPZ = adhocTPZ failTP

--Try to apply a zipper function, and apply identity if it fails
tryTP :: TP (d m) -> TP (d m)
tryTP s = idTP `choiceTP` s

repeatTP :: TP (d m) -> TP (d m)
repeatTP s =  tryTP (mseq (repeatTP s) s)

innermost :: StrategicData (d m) => TP (d m) -> TP (d m)
innermost s =  (tryTP ((innermost s) `mseq` s))
                   `seqTP` oneTPright (innermost s) `seqTP` oneTPdown (innermost s)

innermost'  :: StrategicData (d m) => TP (d m) -> TP (d m)
innermost' s  =  repeatTP (once_buTP s)

outermost  :: StrategicData (d m) => TP (d m) -> TP (d m)
outermost s  =  repeatTP (once_tdTP s)

----------
----
--- TU
----
----------

type TU m d = (forall a. Zipper a -> (m d, Zipper a)) 

applyTU :: (Memoizable dtype memo) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> Zipper (dtype memo) -> (m d, Zipper (dtype memo)) 
applyTU f z = f z 

foldr1TU :: (Monoid (m d), StrategicData (dtype memo), Foldable m) => 
    (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> 
    Zipper (dtype memo) -> (d -> d -> d) -> d
foldr1TU f z red = foldr1 red $ fst (full_tdTU f z) 

foldl1TU :: (Monoid (m d), StrategicData (dtype memo), Foldable m) => 
    (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> 
    Zipper (dtype memo) -> (d -> d -> d) -> d
foldl1TU f z red = foldl1 red $ fst (full_tdTU f z) 

foldrTU :: (Monoid (m d), StrategicData (dtype memo), Foldable m) => 
    (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> 
    Zipper (dtype memo) -> (d -> c -> c) -> c -> c
foldrTU f z red i = foldr red i $ fst (full_tdTU f z) 

foldlTU :: (Monoid (m d), StrategicData (dtype memo), Foldable m) => 
    (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> 
    Zipper (dtype memo) -> (c -> d -> c) -> c -> c
foldlTU f z red i = foldl red i $ fst (full_tdTU f z) 

full_tdTU :: (Monoid (m d), StrategicData (dtype memo)) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))   
full_tdTU f = allTUright (full_buTU f) `seqTU` allTUdown (full_buTU f) `seqTU` f

full_buTU :: (Monoid (m d), StrategicData (dtype memo)) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
full_buTU f = f `seqTU` allTUdown (full_tdTU f) `seqTU` allTUright (full_tdTU f) 

once_tdTU :: (MonadPlus m, Monoid (m d), StrategicData (dtype memo)) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) 
once_tdTU f = f `choiceTU` allTUdown (once_tdTU f)  `choiceTU` allTUright (once_tdTU f) 

once_buTU :: (MonadPlus m, Monoid (m d), StrategicData (dtype memo)) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
once_buTU f = allTUright (once_buTU f) `choiceTU` allTUdown (once_buTU f) `choiceTU` f

stop_tdTU :: (MonadPlus m, Monoid (m d), StrategicData (dtype memo)) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
stop_tdTU f = (f `choiceTU` allTUdown (stop_tdTU f)) `seqTU` allTUright (stop_tdTU f)

stop_buTU :: (MonadPlus m, Monoid (m d), StrategicData (dtype memo)) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
stop_buTU f = allTUright (stop_buTU f) `seqTU` (allTUdown (stop_buTU f) `choiceTU` f)

allTUdown :: (Monoid (m d), StrategicData (dtype memo)) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
allTUdown f z = case down' z of 
         Nothing -> (mempty, z)
         Just d  -> let (v, z') = f d
                    in (v, fromJust $ up z')

allTUright :: (Monoid (m d), StrategicData (dtype memo)) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
allTUright f z = case right z of 
         Nothing -> (mempty, z)
         Just r  -> let (v, z') = f r
                    in (v, fromJust $ left z')

adhocTU :: (Monad m, Typeable a) => (Zipper c -> (m d, Zipper c)) -> (a -> m d) -> (Zipper c -> (m d, Zipper c))
adhocTU f g z = case (zTryReduceM g z) of 
            (Just r, z') -> (r, z')
            (Nothing, z') -> f z'

adhocTUZ :: (Monad m, Typeable a) => (Zipper c -> (m d, Zipper c)) -> (a -> Zipper c -> (m d, Zipper c)) -> (Zipper c -> (m d, Zipper c))
adhocTUZ f g z = case (zTryReduceMZ g z) of 
            (Just r, z') -> (r, z')
            (Nothing, z') -> f z'

seqTU :: (Monoid (m d)) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))-> (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
seqTU x y z =  
  let (yr, z') = y z 
      (xr, z'') = x z'
  in (xr `mappend` yr, z'')

--Sequential composition 
choiceTU :: (MonadPlus m) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
choiceTU x y z = 
  let (yr, z') = y z 
      (xr, z'') = x z'
  in (xr `mplus` yr, z'')

failTU :: (MonadPlus m) => (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
failTU z = (mzero, z)

constTU :: Monad m => d -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
constTU v z = (return v, z)

--Apply a function, fail the composition if it fails
monoTU :: (MonadPlus m, Typeable a) => (a -> m d) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
monoTU = adhocTU failTU

--TODO: fix type signature
--Apply a function with access to the zipper, fail the composition if it fails
monoTUZ :: (MonadPlus m, Typeable a) => (a -> Zipper (dtype memo) -> (m d, Zipper (dtype memo))) -> (Zipper (dtype memo) -> (m d, Zipper (dtype memo)))
monoTUZ = adhocTUZ failTU


--TODO: fix type signature
--TODO: improve using Data.Generics.Aliases, fitting mkT or mkM inside of transM instead of chaining casts 
--elevate a reduction, which can access the zipper, to the zipper level. If the type does not match, returns Nothing 
zTryReduceMZ :: (Typeable a) => (a -> Zipper c -> (b, Zipper c)) -> (Zipper c -> (Maybe b, Zipper c))
zTryReduceMZ f z = case getHole z of 
       Nothing -> (Nothing     , z)
       Just r  -> let (x, z') = f r z 
                  in (Just x, z')


--elevate a reduction to the zipper level. If the type does not match, returns Nothing 
zTryReduceM :: (Typeable a) => (a -> b) -> (Zipper e -> (Maybe b, Zipper e)) -- TU Maybe b
zTryReduceM f z = case getHole z of 
       Nothing -> (Nothing   , z)
       Just r  -> (Just (f r), z)


zTryApplyMZ :: (Typeable a) => (a -> Zipper c -> Maybe (Zipper c)) -> TP c
zTryApplyMZ f z = case getHole z of 
                    Nothing -> Nothing 
                    Just v  -> case (f v z) of 
                                Nothing -> Nothing 
                                Just r  -> Just r

--elevate a transformation to the zipper level. If the type does not match, returns Nothing 
zTryApplyM :: (Typeable a, Typeable b) => (a -> Maybe b) -> TP (c)
zTryApplyM f = transM (join . cast . f . fromJust . cast)

--elevate a transformation to the zipper level. If the type does not match, returns Nothing 
zTryApply :: (Typeable a, Typeable b) => (a -> b) -> TP c
zTryApply f = transM (cast . f . fromJust . cast)

--elevate a transformation to the zipper level. If the type does not match, the zipper remains unchanged
zApply :: (Typeable a, Typeable b) => (a -> b) -> (Zipper c -> Zipper c)
zApply f z = maybe z id (zTryApply f z)