Safe Haskell | None |
---|---|
Language | Haskell2010 |
A registry supports the creation of values out of existing values and functions.
It contains 4 parts:
- values: they are available for building anything else and have their exact value can be shown
- functions: they are used to build other values. Only their type can be shown
- specializations: description of specific values to use while trying to build another value of a given type
- modifiers: function to apply to a newly built value before storing it for future use
A registry is created by using the +:
operator, adding functions or values to the empty end
registry:
registry = val (Config 1) +: val "hello" +: fun add1 +: fun show1 +: end
At the type level a list of all the function inputs and all the outputs is being kept to allow some checks to be made when we want to build a value out of the registry.
It is possible to use the <+>
operator to "override" some configurations:
mocks = fun noLogging +: fun inMemoryDb +: end mocks <+> registry
Synopsis
- data Registry (inputs :: [*]) (outputs :: [*]) = Registry {}
- (<+>) :: Registry is1 os1 -> Registry is2 os2 -> Registry (is1 :++ is2) (os1 :++ os2)
- register :: Typeable a => Typed a -> Registry ins out -> Registry (Inputs a :++ ins) (Output a ': out)
- (+:) :: Typeable a => Typed a -> Registry ins out -> Registry (Inputs a :++ ins) (Output a ': out)
- normalize :: Registry ins out -> Registry (Normalized ins) (Normalized out)
- end :: Registry '[] '[]
- val :: (Typeable a, Show a) => a -> Typed a
- valTo :: forall m a. (Applicative m, Typeable a, Typeable (m a), Show a) => a -> Typed (m a)
- liftProvidedValue :: forall m a. (Applicative m, Typeable a, Typeable (m a), Show a) => a -> Value
- fun :: Typeable a => a -> Typed a
- funTo :: forall m a b. (ApplyVariadic m a b, Typeable a, Typeable b) => a -> Typed b
- funAs :: forall m a b. (ApplyVariadic1 m a b, Typeable a, Typeable b) => a -> Typed b
- specialize :: forall a b ins out. (Typeable a, Contains a out, Typeable b) => b -> Registry ins out -> Registry ins out
- specializePath :: forall path b ins out. (PathToTypeReps path, IsSubset path out, Typeable b) => b -> Registry ins out -> Registry ins out
- specializeVal :: forall a b ins out. (Typeable a, Contains a out, Typeable b, Show b) => b -> Registry ins out -> Registry ins out
- specializePathVal :: forall path b ins out. (PathToTypeReps path, IsSubset path out, Typeable b, Show b) => b -> Registry ins out -> Registry ins out
- specializeValTo :: forall m a b ins out. (Applicative m, Typeable a, Contains a out, Typeable (m b), Typeable b, Show b) => b -> Registry ins out -> Registry ins out
- specializePathValTo :: forall m path b ins out. (Applicative m, PathToTypeReps path, IsSubset path out, Typeable (m b), Typeable b, Show b) => b -> Registry ins out -> Registry ins out
- specializeUnsafe :: forall a b ins out. (Typeable a, Typeable b) => b -> Registry ins out -> Registry ins out
- specializePathUnsafe :: forall path b ins out. (PathToTypeReps path, Typeable b) => b -> Registry ins out -> Registry ins out
- specializeUnsafeVal :: forall a b ins out. (Typeable a, Contains a out, Typeable b, Show b) => b -> Registry ins out -> Registry ins out
- specializePathUnsafeVal :: forall path b ins out. (PathToTypeReps path, Typeable b, Show b) => b -> Registry ins out -> Registry ins out
- specializeUnsafeValTo :: forall m a b ins out. (Applicative m, Typeable a, Typeable (m b), Typeable b, Show b) => b -> Registry ins out -> Registry ins out
- specializePathUnsafeValTo :: forall m path b ins out. (Applicative m, PathToTypeReps path, Typeable (m b), Typeable b, Show b) => b -> Registry ins out -> Registry ins out
- class PathToTypeReps (path :: [*]) where
- someTypeReps :: Proxy path -> NonEmpty SomeTypeRep
- tweak :: forall a ins out. (Typeable a, Contains a out) => (a -> a) -> Registry ins out -> Registry ins out
- tweakUnsafe :: forall a ins out. Typeable a => (a -> a) -> Registry ins out -> Registry ins out
- memoize :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a), Contains (m a) out) => Registry ins out -> IO (Registry ins out)
- memoizeUnsafe :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a)) => Registry ins out -> IO (Registry ins out)
- memoizeAll :: forall m ins out. (MonadIO m, MemoizedActions out) => Registry ins out -> IO (Registry ins out)
- newtype MemoizeRegistry (todo :: [*]) (ins :: [*]) (out :: [*]) = MemoizeRegistry {
- _unMemoizeRegistry :: Registry ins out
- startMemoizeRegistry :: Registry ins out -> MemoizeRegistry out ins out
- makeMemoizeRegistry :: forall todo ins out. Registry ins out -> MemoizeRegistry todo ins out
- class MemoizedActions ls where
- memoizeActions :: MemoizeRegistry ls ins out -> IO (MemoizeRegistry '[] ins out)
- singleton :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a), Contains (m a) out) => Registry ins out -> IO (Registry ins out)
- singletonUnsafe :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a)) => Registry ins out -> IO (Registry ins out)
Documentation
data Registry (inputs :: [*]) (outputs :: [*]) Source #
Container for a list of functions or values
Internally all functions and values are stored as Dynamic
values
so that we can access their representation
(<+>) :: Registry is1 os1 -> Registry is2 os2 -> Registry (is1 :++ is2) (os1 :++ os2) Source #
Append 2 registries together
register :: Typeable a => Typed a -> Registry ins out -> Registry (Inputs a :++ ins) (Output a ': out) Source #
Store an element in the registry
Internally elements are stored as Dynamic
values
(+:) :: Typeable a => Typed a -> Registry ins out -> Registry (Inputs a :++ ins) (Output a ': out) infixr 5 Source #
Add an element to the Registry - Alternative to register where the parentheses can be ommitted
normalize :: Registry ins out -> Registry (Normalized ins) (Normalized out) Source #
Make the lists of types in the Registry unique, either for better display or for faster compile-time resolution with the make function
val :: (Typeable a, Show a) => a -> Typed a Source #
Create a value which can be added to the Registry
valTo :: forall m a. (Applicative m, Typeable a, Typeable (m a), Show a) => a -> Typed (m a) Source #
Create a value which can be added to the Registry
and "lift" it to an Applicative
context
liftProvidedValue :: forall m a. (Applicative m, Typeable a, Typeable (m a), Show a) => a -> Value Source #
Create a "lifted" a Value
funTo :: forall m a b. (ApplyVariadic m a b, Typeable a, Typeable b) => a -> Typed b Source #
This is a shortcut to fun . allTo
where allTo
lifts all the inputs and output
to an Applicative
context
funAs :: forall m a b. (ApplyVariadic1 m a b, Typeable a, Typeable b) => a -> Typed b Source #
This is a shortcut to fun . argsTo
where allTo
lifts all the inputs
to an Applicative context
specialize :: forall a b ins out. (Typeable a, Contains a out, Typeable b) => b -> Registry ins out -> Registry ins out Source #
For a given type a
being currently built
when a value of type b
is required pass a specific value
specializePath :: forall path b ins out. (PathToTypeReps path, IsSubset path out, Typeable b) => b -> Registry ins out -> Registry ins out Source #
specializeVal :: forall a b ins out. (Typeable a, Contains a out, Typeable b, Show b) => b -> Registry ins out -> Registry ins out Source #
This is similar to specialize but additionally uses the Show
instance of b
to display more information when printing the registry out
specializePathVal :: forall path b ins out. (PathToTypeReps path, IsSubset path out, Typeable b, Show b) => b -> Registry ins out -> Registry ins out Source #
specializeValTo :: forall m a b ins out. (Applicative m, Typeable a, Contains a out, Typeable (m b), Typeable b, Show b) => b -> Registry ins out -> Registry ins out Source #
specializePathValTo :: forall m path b ins out. (Applicative m, PathToTypeReps path, IsSubset path out, Typeable (m b), Typeable b, Show b) => b -> Registry ins out -> Registry ins out Source #
specializeUnsafe :: forall a b ins out. (Typeable a, Typeable b) => b -> Registry ins out -> Registry ins out Source #
For a given type a
being currently built
when a value of type b
is required pass a specific
value
specializePathUnsafe :: forall path b ins out. (PathToTypeReps path, Typeable b) => b -> Registry ins out -> Registry ins out Source #
specializeUnsafeVal :: forall a b ins out. (Typeable a, Contains a out, Typeable b, Show b) => b -> Registry ins out -> Registry ins out Source #
specializePathUnsafeVal :: forall path b ins out. (PathToTypeReps path, Typeable b, Show b) => b -> Registry ins out -> Registry ins out Source #
specializeUnsafeValTo :: forall m a b ins out. (Applicative m, Typeable a, Typeable (m b), Typeable b, Show b) => b -> Registry ins out -> Registry ins out Source #
specializePathUnsafeValTo :: forall m path b ins out. (Applicative m, PathToTypeReps path, Typeable (m b), Typeable b, Show b) => b -> Registry ins out -> Registry ins out Source #
class PathToTypeReps (path :: [*]) where Source #
Typeclass for extracting type representations out of a list of types
someTypeReps :: Proxy path -> NonEmpty SomeTypeRep Source #
Instances
(Typeable a, PathToTypeReps rest) => PathToTypeReps (a ': rest) Source # | |
Defined in Data.Registry.Registry someTypeReps :: Proxy (a ': rest) -> NonEmpty SomeTypeRep Source # | |
Typeable a => PathToTypeReps (a ': ([] :: [Type])) Source # | |
Defined in Data.Registry.Registry someTypeReps :: Proxy (a ': []) -> NonEmpty SomeTypeRep Source # |
tweak :: forall a ins out. (Typeable a, Contains a out) => (a -> a) -> Registry ins out -> Registry ins out Source #
Once a value has been computed allow to modify it before storing it This keeps the same registry type
tweakUnsafe :: forall a ins out. Typeable a => (a -> a) -> Registry ins out -> Registry ins out Source #
Once a value has been computed allow to modify it before storing it
Memoization
memoize :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a), Contains (m a) out) => Registry ins out -> IO (Registry ins out) Source #
Instantiating components can trigger side-effects The way the resolution algorithm works a component of type `m a` will be re-executed *everytime* it is needed as a given dependency This section adds support for memoizing those actions (component creation + optional warmup)
Return memoized values for a monadic type
Note that the returned Registry is in IO
because we are caching a value
and this is a side-effect!
memoizeUnsafe :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a)) => Registry ins out -> IO (Registry ins out) Source #
Memoize an action for a given type but don't check if the value is part of the registry outputs
memoizeAll :: forall m ins out. (MonadIO m, MemoizedActions out) => Registry ins out -> IO (Registry ins out) Source #
Memoize *all* the output actions of a Registry when they are creating effectful components
This relies on a helper data structure MemoizeRegistry
tracking the types already
memoized and a typeclass MemoizedActions going through the list of out
types to process them
one by one. Note that a type of the form a
will not be memoized (only `m a`)
newtype MemoizeRegistry (todo :: [*]) (ins :: [*]) (out :: [*]) Source #
MemoizeRegistry | |
|
startMemoizeRegistry :: Registry ins out -> MemoizeRegistry out ins out Source #
makeMemoizeRegistry :: forall todo ins out. Registry ins out -> MemoizeRegistry todo ins out Source #
class MemoizedActions ls where Source #
memoizeActions :: MemoizeRegistry ls ins out -> IO (MemoizeRegistry '[] ins out) Source #
Instances
MemoizedActions ([] :: [Type]) Source # | |
Defined in Data.Registry.Registry memoizeActions :: MemoizeRegistry [] ins out -> IO (MemoizeRegistry [] ins out) Source # | |
MemoizedActions rest => MemoizedActions (a ': rest) Source # | |
Defined in Data.Registry.Registry memoizeActions :: MemoizeRegistry (a ': rest) ins out -> IO (MemoizeRegistry [] ins out) Source # | |
(MonadIO m, Typeable a, Typeable (m a), MemoizedActions rest) => MemoizedActions (m a ': rest) Source # | |
Defined in Data.Registry.Registry memoizeActions :: MemoizeRegistry (m a ': rest) ins out -> IO (MemoizeRegistry [] ins out) Source # |