Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
- Basic Provenance Monad Transformer
- Dynamically typed Provenance objects
- Type constraint on data stored in PObject
- ProvM instantiated (Map Text PObject)
- Abstraction barrier to isolate the provenence type from the result type.
- Operations in ProvM
- Operations in Prov instantiation
- Operation on PObject
- For testing invariants
Synopsis
- newtype ProvM t m a = ProvM (StateT (StrictMaybe t) m a)
- data PObject
- type Provenance t = (Typeable t, ToJSON t, Show t, NoThunks t)
- type Prov m a = ProvM Store m a
- data BlackBox t
- lift ∷ (MonadTrans t, Monad m) ⇒ m a → t m a
- putM ∷ Monad m ⇒ s → ProvM s m ()
- getM ∷ Monad m ⇒ ProvM s m (BlackBox s)
- modifyM ∷ Monad m ⇒ (t → t) → ProvM t m ()
- modifyWithBlackBox ∷ Monad m ⇒ BlackBox p → (p → t → t) → ProvM t m ()
- runProv ∷ Monad m ⇒ Prov m t → m t
- runWithProv ∷ Monad m ⇒ Prov m t → m (t, Store)
- runOtherProv ∷ Monad m ⇒ s1 → ProvM s1 m a → ProvM s2 m (a, BlackBox s1)
- liftProv ∷ Monad m ⇒ ProvM s1 m a → s1 → (a → s1 → s2 → s2) → ProvM s2 m a
- dump ∷ Monad m ⇒ Prov m String
- store ∷ ∀ t m. (Provenance t, Monad m) ⇒ Text → m t → Prov m t
- push ∷ (Provenance t, Monad m) ⇒ Text → t → Prov m ()
- pull ∷ ∀ t m. (Monad m, Typeable t) ⇒ Text → Prov m (BlackBox t)
- update ∷ ∀ t m. (Provenance t, Monad m) ⇒ Text → (t → t) → Prov m ()
- updateWithBlackBox ∷ ∀ t m s. (Provenance t, Monad m) ⇒ Text → BlackBox s → (s → t → t) → Prov m ()
- pushOtherProv ∷ (Provenance s1, Monad m) ⇒ Text → s1 → ProvM s1 m a → ProvM Store m a
- runWithProvM ∷ Monad m ⇒ s → ProvM s m a → m (a, s)
- runProvM ∷ Monad m ⇒ ProvM s m b → m b
- find ∷ ∀ t k. (Ord k, Typeable t) ⇒ k → Map k PObject → StrictMaybe t
- observe ∷ Store → String
- preservesNothing ∷ Monad m ⇒ ProvM t m a → m Bool
- preservesJust ∷ Monad m ⇒ t → ProvM t m a → m Bool
Documentation
The Provenance Monad is just the StateT transformer wrapped in a newtype, where the state is (StrictMaybe t). By running the state transformer with an initial state of SNothing we indicate we are not collecting provenance. With an initial state of (SJust t), we are collecting provenance. If we start off as SNothing, then actions on the state are no-ops and are ignored. We maintain several invariants. If we start with SNothing, we get SNothing, and if we start with (SJust s) we end up with (SJust t)
invariant1 (ProvM m) = do (_,SNothing) <- runStateT m SNothing invariant2 (ProvM m) = do (_,SJust t) <- runStateT m (SJust 1)
The second invariant is that regardless of whether we compute provenance or not, the non-provenance part is the same. Currently this is enforced by the BlackBox type and its API.
invariant3 (ProvM m) = do (ans1,SNothing) <- runStateT m SNothing (ans2,SJust p) <- runStateT m (SJust s) pure(ans1 == ans2)
All operations that read the provenance (i.e the state) return a (BlackBox t). BlackBoxes can only be used to modify provenance.
ProvM (StateT (StrictMaybe t) m a) |
Basic Provenance Monad Transformer
Dynamically typed Provenance objects
type Provenance t = (Typeable t, ToJSON t, Show t, NoThunks t) Source #
Since PObjects are dynamically typed, What operations are required on a type to act as Provenance? We might want to add or subtract some properties from this list.
Type constraint on data stored in PObject
type Prov m a = ProvM Store m a Source #
A special case of the ProvM Monad, where the state type is Store
a (Map Text PObject), where PObject is a dynamically typed value. This
allows the collection of a Set of provenance values, indexed by keys of
type Text. As in the ProvM monad, if run with runProv
operations on
the Store are ignored.
ProvM instantiated (Map Text PObject)
BlackBox is an abstraction barrier. Reading the provenance is always returned in a BlackBox. The only way to open the BlackBox is to use one of the BlackBlox eliminator operations: modifyWithBlackBox or runOtherProv, that merge the contents of the BlackBox into the current provenance. This ensures that there is no easy way for the provenance computation to have an effect on the result of the underlying computation.
Abstraction barrier to isolate the provenence type from the result type.
Operations in ProvM
lift ∷ (MonadTrans t, Monad m) ⇒ m a → t m a Source #
Lift a computation from the argument monad to the constructed monad.
getM ∷ Monad m ⇒ ProvM s m (BlackBox s) Source #
Extract the current provenance. The result is wrapped in a BlackBox. This ensures that provenance cannot be used in the non-provenance part of the computation.
modifyM ∷ Monad m ⇒ (t → t) → ProvM t m () Source #
Modify the provenance if collecting provenance, otherwise do nothing.
runProv ∷ Monad m ⇒ Prov m t → m t Source #
Run the (Prov m a) computation and ignore the provenance part
runWithProv ∷ Monad m ⇒ Prov m t → m (t, Store) Source #
Run the (Prov m a) computation, compute and return the provenance as well as the result.
runOtherProv ∷ Monad m ⇒ s1 → ProvM s1 m a → ProvM s2 m (a, BlackBox s1) Source #
Run a provenance computation, with provenance s1, and lift the result to a provenance computation with provenance s2. Use the active state of the s2 computation to decide if we actually compute the provenance s1. The s1 result is returned in a BlackBox. This ensures that provenance cannot be used in the non-provenance part of the computation.
liftProv ∷ Monad m ⇒ ProvM s1 m a → s1 → (a → s1 → s2 → s2) → ProvM s2 m a Source #
lift a provenenace computation from one provenance type (s1) to another (s2)
dump ∷ Monad m ⇒ Prov m String Source #
Return a String representation of the current provenance store.
Operations in Prov instantiation
store ∷ ∀ t m. (Provenance t, Monad m) ⇒ Text → m t → Prov m t Source #
Run a computation in the underlying monad (m), return that value in the (Prov m) monad. As a side effect store that value under the given key equivalent to: store key m = do { a <- lift m; push key a; pure a}
push ∷ (Provenance t, Monad m) ⇒ Text → t → Prov m () Source #
Push a key value pair into the provenance store. Overwrites any existing POjects stored under that key.
pull ∷ ∀ t m. (Monad m, Typeable t) ⇒ Text → Prov m (BlackBox t) Source #
Reads the provenance value at a key. The value is returned in a BlackBox. There are 3 reasons the BlackBox may be empty. 1) The computation is not collecting provenance. 2) The map does not contain the key 3) The value at the key has the wrong type.
update ∷ ∀ t m. (Provenance t, Monad m) ⇒ Text → (t → t) → Prov m () Source #
Modify the value stored at the given key. If the key isn't found or the PObject at that key has the wrong type, do nothing.
updateWithBlackBox ∷ ∀ t m s. (Provenance t, Monad m) ⇒ Text → BlackBox s → (s → t → t) → Prov m () Source #
Modify the value stored at the given key using a value in a BlackBox. if the key isn't found, or the PObject at that key has the wrong type, do nothing.
pushOtherProv ∷ (Provenance s1, Monad m) ⇒ Text → s1 → ProvM s1 m a → ProvM Store m a Source #
Push the provenance of a computation, under the given key. The computation has provenance s1, and lift the result to a provenance computation with provenance Store. Use the active state of the Store computation to decide if we actually want to compute the provenance s1, and push it, or simply ignore it.
runWithProvM ∷ Monad m ⇒ s → ProvM s m a → m (a, s) Source #
Run and compute the result as well as the provenance. Supply an initial value for the provenance.
runProvM ∷ Monad m ⇒ ProvM s m b → m b Source #
Run the computation with SNothing. Expend no resources to compute provenance.
Operation on PObject
find ∷ ∀ t k. (Ord k, Typeable t) ⇒ k → Map k PObject → StrictMaybe t Source #
Find a value for a given key from a Store (Map Text PObject). If the Store does not have that key, or the PObject at that key does not have the right type, returns SNothing. If the type context of the call does not fix the type, one can use a type application like: find @Bool key map