{-# language RankNTypes #-} {-# language StandaloneDeriving #-} {-# language TemplateHaskell #-} {-# language UndecidableInstances #-} module Rock.Traces where import Protolude import Data.Dependent.Map(DMap, GCompare, DSum((:=>))) import qualified Data.Dependent.Map as DMap import Data.Dependent.Sum import Data.Functor.Classes import Text.Show.Deriving import Rock.HashTag import Rock.Hashed data ValueDeps f a = ValueDeps { value :: !(Hashed a) , dependencies :: !(DMap f Hashed) } return [] deriving instance (Show a, ShowTag f Hashed) => Show (ValueDeps f a) instance ShowTag f Hashed => Show1 (ValueDeps f) where liftShowsPrec = $(makeLiftShowsPrec ''ValueDeps) type Traces f = DMap f (ValueDeps f) verifyDependencies :: Monad m => (forall a'. f a' -> m (Hashed a')) -> ValueDeps f a -> m (Maybe a) verifyDependencies fetchHash (ValueDeps hashedValue deps) = do upToDate <- allM (DMap.toList deps) $ \(depKey :=> depValue) -> do depValue' <- fetchHash depKey return $ hash depValue == hash depValue' return $ if upToDate then Just $ unhashed hashedValue else Nothing where allM :: Monad m => [a] -> (a -> m Bool) -> m Bool allM [] _ = return True allM (x:xs) p = do b <- p x if b then allM xs p else return False record :: (GCompare f, HashTag f) => f a -> a -> DMap f Identity -> Traces f -> Traces f record k v deps = DMap.insert k $ ValueDeps (hashed k v) $ DMap.mapWithKey (\k' (Identity v') -> hashed k' v') deps