packages feed

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

{-# LANGUAGE MultiParamTypeClasses, ScopedTypeVariables, AllowAmbiguousTypes, DeriveDataTypeable #-}
module Language.Memo.Safe.AGMemo where 

import Data.Generics.Zipper
import Data.Generics.Aliases
import Language.ZipperAG
import Language.StrategicData
import Data.Data
import Data.Maybe (fromJust)
import Data.List (union)

-- MemoAG

atChild eval t i = let (v,t',d) = eval (t.$i)
                   in  (v, parent t',[Child i]) 

atParent eval t = let n = arity t 
                      (v,t',d) = eval (parent t)
                  in  (v, t'.$n, [Parent])

atRight eval t  = let (v,t',d) = eval (t.$>1)
                  in  (v, (t'.$<1),[AtRight])

atLeft eval t   = let (v,t',d) = eval (t.$<1)
                  in  (v, (t'.$>1),[AtLeft])

class MemoTable m => Memo att m a where
  mlookup :: att -> m -> Maybe a
  massign :: att -> a -> m -> m

data Dependency = Parent | Child Int | AtRight | AtLeft
 deriving (Data, Eq, Show)

class Typeable m => MemoTable m where 
  isValidMemoTable :: m -> Bool
  invalidateMemoTable :: m -> m 
  validateMemoTable :: m -> m 
  getDependencies :: m -> [Dependency]
  addDependency :: Dependency -> m -> m
  -- consider deleting memo class for this here:
  -- mstore :: 
  -- mlookup :: 

addDependencies :: MemoTable m => [Dependency] -> m -> m 
addDependencies d m = validateMemoTable $ foldr addDependency m d

class (Typeable dtype, MemoTable m) => Memoizable dtype m where 
  getMemoTable :: dtype m -> m 
  updMemoTable :: (m -> m) -> dtype m -> dtype m
  invalidateDependencies :: Zipper (dtype m) -> Zipper (dtype m)
  invalidateDependencies z = 
    if isValidMemoTable (memoTable z)
      then let z'  = upd' invalidateMemoTable z
               dep = getDependencies (memoTable z)
               fromDep Parent r = parent r 
               fromDep (Child n) r = r.$n
               fromDep AtRight r = r.$>1
               fromDep AtLeft  r = r.$<1
               unFromDep Parent r = r.$(arity z') 
               unFromDep (Child n) r = parent r
               unFromDep AtRight r = r.$<1
               unFromDep AtLeft  r = r.$>1
           in foldr (\d x -> unFromDep d $ invalidateDependencies (fromDep d x)) z' dep
      else z


-- type AGTree_m dtype m a = Zipper (dtype m) -> (a, Zipper (dtype m)) 
type AGTree_m dtype m a =  (Zipper (dtype m) -> (a, Zipper (dtype m), [Dependency]))


memo :: (Memoizable dtype m, Memo attr m a) => 
        attr -> 
        AGTree_m dtype m a -> 
        AGTree_m dtype m a
memo attr eval = \z ->
   case (isValidMemoTable (memoTable z), mlookup attr (memoTable z)) of
    (True, Just v)   -> (v,z, getDependencies (memoTable z))
    _                -> let (v,z', d) = eval z
                        in  (v, upd' (addDependencies d . massign attr v) z', d) 



memoTable :: forall dtype m. (Memoizable dtype m) => Zipper (dtype m) -> m
memoTable zx = let a' = (fromJust $ getHole zx) :: dtype m
               in getMemoTable a' 


-- "forced typechecking"
upd' :: Memoizable dtype m => (m -> m) -> Zipper (dtype m) -> Zipper (dtype m)
upd' f z = setHole (aux f z) z
 where aux :: (Memoizable dtype m) => (m -> m) -> Zipper (dtype m) -> dtype m
       aux f = updMemoTable f . fromJust . getHole