-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | data structure for assembling components
--   
--   This library provides a <a>Registry</a> which is a data structure
--   containing a list of functions and values representing dependencies in
--   a directed acyclic graph. A <a>make</a> function can then be used to
--   create a value of a specific type out of the registry. You can start
--   with the <a>README</a> for a full description of the library.
@package registry
@version 0.1.2.6


-- | Cache for individual IO values when we wish to memoize actions for
--   database connection pools for example
--   
--   This is inspired by
--   <a>https://hackage.haskell.org/package/io-memoize</a>
module Data.Registry.Internal.Cache

-- | A thread-safe write-once cache. If you need more functionality, (e.g.
--   multiple write, cache clearing) use an <a>MVar</a> instead.
newtype Cache a
Cache :: MVar (Maybe a) -> Cache a

-- | Fetch the value stored in the cache, or call the supplied fallback and
--   store the result, if the cache is empty.
fetch :: forall a m. MonadIO m => Cache a -> m a -> m a

-- | Create an empty cache.
newCache :: IO (Cache a)
instance GHC.Classes.Eq (Data.Registry.Internal.Cache.Cache a)


-- | Utility functions to display or manipulate types
module Data.Registry.Internal.Reflection

-- | Return true if the type of this type rep represents a function
isFunction :: SomeTypeRep -> Bool

-- | Show the full type of a typeable value
showFullValueType :: Typeable a => a -> Text

-- | Show the full type of a typeable function
showFullFunctionType :: Typeable a => a -> ([Text], Text)

-- | Show the full type of a typeable value where nested types like
--   <tt>IO[Int]</tt> or functions are represented and non GHC types are
--   shown with their module names
showTheFullValueType :: forall (r1 :: RuntimeRep) (arg :: TYPE r1). TypeRep arg -> Text

-- | Show the full type of a typeable value where nested types like IO[Int]
--   or functions are represented and non GHC types are shown with their
--   module names
showTheFullFunctionType :: forall (r1 :: RuntimeRep) (arg :: TYPE r1). TypeRep arg -> ([Text], Text)

-- | Show a type like <tt>m a</tt>
showNested :: SomeTypeRep -> SomeTypeRep -> Text

-- | Show a single type. Don't display the module for GHC types
showSingleType :: SomeTypeRep -> Text

-- | Return true if the module name can be shown
mustShowModuleName :: Text -> Bool

-- | Tweak some standard module names for better display
tweakNested :: Text -> Text

-- | This is an attempt to better render "nested" types like IO (Maybe
--   Text) The input value is <tt>"IO Maybe Text"</tt> and the output text
--   will be <tt>"IO (Maybe Text)"</tt> This will unfortunately not work
--   with types having several type parameters like <tt>IO (Either Text
--   Int)</tt>
parenthesizeNested :: Text -> Text

-- | Show a type with its module name
showWithModuleName :: SomeTypeRep -> Text


-- | List of types used inside the Registry
module Data.Registry.Internal.Types

-- | A <a>Value</a> is the <a>Dynamic</a> representation of a Haskell value
--   + its description It is either provided by the user of the Registry or
--   created as part of the resolution algorithm If a <a>Context</a> is
--   present for a a created value this means that this value has been
--   written as the result of a specialization. The first type of the list
--   of types in the context is the types under which the specialization
--   must apply and the other types are "parents" of the current value in
--   the value graph
data Value
CreatedValue :: Dynamic -> ValueDescription -> Maybe Context -> Maybe Specialization -> Dependencies -> Value
ProvidedValue :: Dynamic -> ValueDescription -> Value

-- | This registers the specific context in which a valu | Description of a
--   value. It might just have a description for its type when it is a
--   value created by the resolution algorithm
data ValueDescription
ValueDescription :: Text -> Maybe Text -> ValueDescription
[_valueType] :: ValueDescription -> Text
[_valueValue] :: ValueDescription -> Maybe Text

-- | Describe a value with its type and actual content
describeValue :: (Typeable a, Show a) => a -> ValueDescription

-- | Describe a value with only its type
describeTypeableValue :: Typeable a => a -> ValueDescription

-- | Show a Value from the <tt>Registry</tt>
showValue :: Value -> Text

-- | Create a Value from a Haskell value, using its Show instance for its
--   description
createValue :: (Typeable a, Show a) => a -> Value

-- | Make a ProvidedValue
makeProvidedValue :: Dynamic -> ValueDescription -> Value

-- | make a CreatedValue in no particular context
makeCreatedValue :: Dynamic -> ValueDescription -> Dependencies -> Value

-- | Create a Value from a Haskell value, with only its <a>Typeable</a>
--   description
createTypeableValue :: Typeable a => a -> Value

-- | Create a Value from a <a>Dynamic</a> value and some description
createDynValue :: Dynamic -> Text -> Value

-- | Type representation of a <a>Value</a>
valueDynTypeRep :: Value -> SomeTypeRep

-- | Dynamic representation of a <a>Value</a>
valueDyn :: Value -> Dynamic

-- | The description for a <a>Value</a>
valDescription :: Value -> ValueDescription

-- | The dependencies for a <a>Value</a>
valDependencies :: Value -> Dependencies

-- | A ValueDescription as <a>Text</a>. If the actual content of the
--   <a>Value</a> is provided display the type first then the content
valDescriptionToText :: ValueDescription -> Text

-- | Return the creation context for a given value when it was created as
--   the result of a "specialization"
specializationContext :: Value -> Maybe Context

-- | Return the specialization used to create a specific values
usedSpecialization :: Value -> Maybe Specialization

-- | Return True if a type is part of the specialization context of a Value
isInSpecializationContext :: SomeTypeRep -> Value -> Bool

-- | Return True if a value has transitives dependencies which are
--   specialized values
hasSpecializedDependencies :: Specializations -> Value -> Bool

-- | A Function is the <a>Dynamic</a> representation of a Haskell function
--   + its description
data Function
Function :: Dynamic -> FunctionDescription -> Function

-- | Create a <a>Function</a> value from a Haskell function
createFunction :: Typeable a => a -> Function

-- | Description of a <a>Function</a> with input types and output type
data FunctionDescription
FunctionDescription :: [Text] -> Text -> FunctionDescription
[_inputTypes] :: FunctionDescription -> [Text]
[_outputType] :: FunctionDescription -> Text

-- | Describe a <a>Function</a> (which doesn't have a <a>Show</a> instance)
--   that can be put in the <tt>Registry</tt>
describeFunction :: Typeable a => a -> FunctionDescription

-- | Show a Function as <a>Text</a> using its Description
showFunction :: Function -> Text

-- | The Description of a <a>Function</a>
funDescription :: Function -> FunctionDescription

-- | Dynamic representation of a <a>Function</a>
funDyn :: Function -> Dynamic

-- | Type representation of a <a>Function</a>
funDynTypeRep :: Function -> SomeTypeRep

-- | A <a>FunctionDescription</a> as <a>Text</a>
funDescriptionToText :: FunctionDescription -> Text

-- | Return True if a <a>Function</a> has some input parameters
hasParameters :: Function -> Bool

-- | A Typed value or function can be added to a <tt>Registry</tt> It is
--   either a value, having both <a>Show</a> and <a>Typeable</a>
--   information or a function having just <a>Typeable</a> information
data Typed a
TypedValue :: Value -> Typed a
TypedFunction :: Function -> Typed a

-- | This is a list of functions (or "constructors") available for
--   constructing values
newtype Functions
Functions :: [Function] -> Functions

-- | Display a list of constructors
describeFunctions :: Functions -> Text

-- | Add one more Function to the list of Functions
addFunction :: Function -> Functions -> Functions

-- | List of values available which can be used as parameters to
--   constructors for building other values
newtype Values
Values :: [Value] -> Values
[unValues] :: Values -> [Value]

-- | Display a list of values
describeValues :: Values -> Text

-- | Add one more Value to the list of Values
addValue :: Value -> Values -> Values

-- | The types of values that we are trying to build at a given moment of
--   the resolution algorithm. IMPORTANT: this is a *stack*, the deepest
--   elements in the value graph are first in the list
newtype Context
Context :: [SomeTypeRep] -> Context
[_contextStack] :: Context -> [SomeTypeRep]

-- | The values that a value depends on
newtype Dependencies
Dependencies :: [Value] -> Dependencies
[unDependencies] :: Dependencies -> [Value]

-- | The values types that a value depends on
newtype DependenciesTypes
DependenciesTypes :: [SomeTypeRep] -> DependenciesTypes
[unDependenciesTypes] :: DependenciesTypes -> [SomeTypeRep]
dependenciesTypes :: Dependencies -> DependenciesTypes

-- | The dependencies of a value + the value itself
dependenciesOn :: Value -> Dependencies

-- | Specification of values which become available for construction when a
--   corresponding type comes in context
newtype Specializations
Specializations :: [Specialization] -> Specializations
[unSpecializations] :: Specializations -> [Specialization]

-- | A specialization is defined by a path of types, from top to bottom in
--   the value graph and target value, which is the value to use when we
--   need a value on that type on that path. For example:
--   specializationPath = [App, PaymentEngine, TransactionRepository]
--   specializationValue = DatabaseConfig "localhost" 5432 This means that
--   need to use this <tt>DatabaseConfig</tt> whenever trying to find
--   inputs needed to create a TransactionRepository if that repository is
--   necessary to create a PaymentEngine, itself involved in the creation
--   of the App
data Specialization
Specialization :: NonEmpty SomeTypeRep -> Value -> Specialization
[_specializationPath] :: Specialization -> NonEmpty SomeTypeRep
[_specializationValue] :: Specialization -> Value

-- | First type of a specialization
specializationStart :: Specialization -> SomeTypeRep

-- | Last type of a specialization
specializationEnd :: Specialization -> SomeTypeRep

-- | Return the type of the replaced value in a specialization
specializationTargetType :: Specialization -> SomeTypeRep

-- | A specialization is applicable to a context if all its types are part
--   of that context, in the right order
isContextApplicable :: Context -> Specialization -> Bool

-- | Return the specifications valid in a given context
applicableTo :: Specializations -> Context -> Specializations

-- | The depth of a specialization in a context is the the index of the
--   <tt>deepest</tt> type of that specialization in the stack of types of
--   that context is the one having its "deepest" type (in the value graph)
--   the "deepest" in the current context If there is a tie we take the
--   "highest" highest type of each
specializedContext :: Context -> Specialization -> SpecializedContext

-- | For a given context this represents the position of a specialization
--   path in that context. startRange is the index of the start type of the
--   specialization endRange is the index of the last type.
data SpecializedContext
SpecializedContext :: Maybe Int -> Maybe Int -> SpecializedContext
[_startRange] :: SpecializedContext -> Maybe Int
[_endRange] :: SpecializedContext -> Maybe Int

-- | Restrict a given context to the types of a specialization
--   specializedContext :: Context -&gt; Specialization -&gt; Context
--   specializedContext (Context cs) specialization = Context $ P.dropWhile
--   (/= specializationEnd specialization) . dropWhileEnd (/=
--   specializationStart specialization) $ cs
--   
--   In a given context, create a value as specified by a specialization
--   the full context is necessary since the specificationPath is only a
--   subpath of a given creation context
createValueFromSpecialization :: Context -> Specialization -> Value

-- | Display a list of specializations for the Registry, just showing the
--   context (a type) in which a value must be selected
describeSpecializations :: Specializations -> Text

-- | List of functions modifying some values right after they have been
--   built. This enables "tweaking" the creation process with slightly
--   different results. Here SomeTypeRep is the target value type
--   <tt>a</tt> and
newtype Modifiers
Modifiers :: [(SomeTypeRep, Function)] -> Modifiers

-- | Display a list of modifiers for the Registry, just showing the type of
--   the modified value
describeModifiers :: Modifiers -> Text
instance GHC.Base.Monoid Data.Registry.Internal.Types.Modifiers
instance GHC.Base.Semigroup Data.Registry.Internal.Types.Modifiers
instance GHC.Show.Show Data.Registry.Internal.Types.Modifiers
instance GHC.Show.Show Data.Registry.Internal.Types.SpecializedContext
instance GHC.Classes.Eq Data.Registry.Internal.Types.SpecializedContext
instance GHC.Base.Monoid Data.Registry.Internal.Types.Values
instance GHC.Base.Semigroup Data.Registry.Internal.Types.Values
instance GHC.Show.Show Data.Registry.Internal.Types.Values
instance GHC.Base.Monoid Data.Registry.Internal.Types.Specializations
instance GHC.Base.Semigroup Data.Registry.Internal.Types.Specializations
instance GHC.Show.Show Data.Registry.Internal.Types.Specializations
instance GHC.Base.Monoid Data.Registry.Internal.Types.Dependencies
instance GHC.Base.Semigroup Data.Registry.Internal.Types.Dependencies
instance Data.Hashable.Class.Hashable Data.Registry.Internal.Types.Dependencies
instance GHC.Show.Show Data.Registry.Internal.Types.Dependencies
instance GHC.Show.Show Data.Registry.Internal.Types.Value
instance GHC.Show.Show Data.Registry.Internal.Types.Specialization
instance GHC.Base.Monoid Data.Registry.Internal.Types.DependenciesTypes
instance GHC.Base.Semigroup Data.Registry.Internal.Types.DependenciesTypes
instance GHC.Show.Show Data.Registry.Internal.Types.DependenciesTypes
instance GHC.Classes.Eq Data.Registry.Internal.Types.DependenciesTypes
instance GHC.Base.Monoid Data.Registry.Internal.Types.Context
instance GHC.Base.Semigroup Data.Registry.Internal.Types.Context
instance GHC.Show.Show Data.Registry.Internal.Types.Context
instance Data.Hashable.Class.Hashable Data.Registry.Internal.Types.Context
instance GHC.Classes.Eq Data.Registry.Internal.Types.Context
instance GHC.Base.Monoid Data.Registry.Internal.Types.Functions
instance GHC.Base.Semigroup Data.Registry.Internal.Types.Functions
instance GHC.Show.Show Data.Registry.Internal.Types.Functions
instance GHC.Show.Show Data.Registry.Internal.Types.Function
instance GHC.Show.Show Data.Registry.Internal.Types.FunctionDescription
instance GHC.Classes.Eq Data.Registry.Internal.Types.FunctionDescription
instance GHC.Show.Show Data.Registry.Internal.Types.ValueDescription
instance GHC.Classes.Eq Data.Registry.Internal.Types.ValueDescription
instance GHC.Classes.Ord Data.Registry.Internal.Types.SpecializedContext
instance Data.Hashable.Class.Hashable Data.Registry.Internal.Types.Value
instance Data.Hashable.Class.Hashable Data.Registry.Internal.Types.ValueDescription

module Data.Registry.Internal.Statistics

-- | This datatype records: - the created values - the applied functions -
--   the specializations used to create values
data Statistics
Statistics :: Operations -> Values -> Statistics
[operations] :: Statistics -> Operations
[values] :: Statistics -> Values

-- | A list of function applications created when creating a value out of
--   the Registry
type Operations = [AppliedFunction]

-- | List of distinct paths from the root of the value graph to a leaf
type Paths = [[Value]]

-- | A function application with an output value and a list of input values
data AppliedFunction
AppliedFunction :: Value -> [Value] -> AppliedFunction
[_outputValue] :: AppliedFunction -> Value
[_inputValues] :: AppliedFunction -> [Value]
initStatistics :: Values -> Statistics

-- | Return the specializations used during the creation of values
usedSpecializations :: Statistics -> [Specialization]

-- | Return the list of distinct paths from the root of a value graph to
--   leaves of that graph. This can be used to check if a given value was
--   indeed used according to a given specialization
allValuesPaths :: Statistics -> Paths

-- | Return all the paths from a given value to all its dependencies
valuePaths :: Value -> Paths
instance GHC.Show.Show Data.Registry.Internal.Statistics.Statistics
instance GHC.Show.Show Data.Registry.Internal.Statistics.AppliedFunction
instance GHC.Base.Semigroup Data.Registry.Internal.Statistics.Statistics
instance GHC.Base.Monoid Data.Registry.Internal.Statistics.Statistics


-- | Internal monad for the resolution algorithm
--   
--   <ul>
--   <li>we keep some state for the list of created values</li>
--   <li>we collect the applied functions as <a>Operations</a></li>
--   <li>we might exit with a Left value if we can't build a value</li>
--   </ul>
module Data.Registry.Internal.Stack

-- | Monadic stack for the resolution algorithm
type Stack a = StateT Statistics (Either Text) a

-- | Return a value from the Stack if possible
runStack :: Stack a -> Either Text a

-- | Return a value from the Stack if possible
runStackWithValues :: Values -> Stack a -> Either Text a
execStack :: Stack a -> Either Text Values

-- | Return the state of the stack after executing the action This returns
--   the list of built values
execStackWithValues :: Values -> Stack a -> Either Text Values

-- | Return the list of applied functions after resolution
evalStack :: Stack a -> Either Text Statistics
evalStackWithValues :: Values -> Stack a -> Either Text Statistics

-- | Get the current list of values
getValues :: Stack Values

-- | Get the current list of operations
getOperations :: Stack Operations

-- | Modify the current list of values
modifyValues :: (Values -> Values) -> Stack ()
modifyOperations :: (Operations -> Operations) -> Stack ()
modifyStatistics :: (Statistics -> Statistics) -> Stack ()

-- | Store a function application in the list of operations
functionApplied :: Value -> [Value] -> Stack ()


-- | Utility functions to work with <a>Dynamic</a> values
module Data.Registry.Internal.Dynamic

-- | Apply a function to a list of <a>Dynamic</a> values
applyFunction :: Function -> [Value] -> Either Text Value

-- | Apply a Dynamic function to a list of Dynamic values
applyFunctionDyn :: Dynamic -> [Dynamic] -> Either Text Dynamic

-- | Apply just one dynamic parameter to a dynamic function
applyOneParam :: Dynamic -> Dynamic -> Either Text Dynamic

-- | If Dynamic is a function collect all its input types
collectInputTypes :: Function -> [SomeTypeRep]

-- | If the input type is a function type return its output type
outputType :: SomeTypeRep -> SomeTypeRep


-- | Internal structure of a <tt>Registry</tt> and associated functions
module Data.Registry.Internal.Registry

-- | Find a value having a target type from: - a list of "preferred values"
--   (Specializations) to select when we are trying to find the targe in a
--   specific context (Context). Context describes the types of values we
--   are currently trying to (recursively) make
--   
--   <ul>
--   <li>a list of already created values (Values)</li>
--   </ul>
--   
--   3 subtleties: 1. if there are specialized values we need to find the
--   most specialized for the current context, that is the one having its
--   "targetType" the "lowest" in the values graph
--   
--   <ol>
--   <li>if an already created value has the right type but if it is a
--   specialization and the type we are looking for is not in the
--   specialization context then we cannot use that value, we need to
--   recreate a brand new one</li>
--   <li>if an already created value has the right type and is not
--   specialized but if there is an incompatible specialization for one of
--   its dependencies then it cannot be used</li>
--   </ol>
findValue :: SomeTypeRep -> Context -> Specializations -> Values -> Maybe Value

-- | Among all the applicable specializations take the most specific one if
--   there exists any
findBestSpecializedValue :: SomeTypeRep -> Context -> Specializations -> Maybe Value

-- | Among all the created values, take a compatible one
--   
--   <ul>
--   <li>if that value is a specialized value or has specialized
--   dependencies it must be compatible with the current context</li>
--   </ul>
findCompatibleCreatedValue :: SomeTypeRep -> Specializations -> Values -> Maybe Value

-- | Find a constructor function returning a target type from a list of
--   constructors
findConstructor :: SomeTypeRep -> Functions -> Maybe Function

-- | Given a newly built value, check if there are modifiers for that value
--   and apply them before "storing" the value which means adding it on top
--   of the registry, represented by the <a>Values</a> state in StateT
--   Values. We use a StateT Either because applying modifiers could fail
--   and we want to catch and report the error. Note that this error would
--   be an implementation error (and not a user error) since at the
--   type-level everything should be correct
storeValue :: Modifiers -> Value -> Stack Value


-- | Untyped implementation of the functionalities in <a>Make</a>
module Data.Registry.Internal.Make

-- | Make a value from a desired output type represented by SomeTypeRep and
--   a list of possible constructors A <a>Context</a> is passed in the form
--   of a stack of the types we are trying to build so far Functions is the
--   list of all the constructors in the Registry Specializations is a list
--   of specific values to use in a given context, overriding the normal
--   search Modifiers is a list of functions to apply right before a value
--   is stored in the Registry
makeUntyped :: SomeTypeRep -> Context -> Functions -> Specializations -> Modifiers -> Stack (Maybe Value)

-- | Make the input values of a given function When a value has been made
--   it is placed on top of the existing registry so that it is memoized if
--   needed in subsequent calls
makeInputs :: [SomeTypeRep] -> Context -> Functions -> Specializations -> Modifiers -> Stack [Value]


-- | Nested datatype to track the resolution algorithm
--   
--   From this data type we can draw a graph of the full instantation of a
--   value
module Data.Registry.Internal.Dot

-- | Make a list of graph edges from the list of function applications
makeEdges :: Operations -> [(Value, Value)]

-- | A DOT graph
newtype Dot
Dot :: Text -> Dot
[unDot] :: Dot -> Text
type DotState = State ValuesByType
type ValuesByType = Map SomeTypeRep ValueHashes
type Hash = Int
type ValueId = Int
type ValueHashes = [Hash]
type Edge = (Value, Value)
type Edges = [Edge]
type ValueCounter = Maybe Int

-- | Make a DOT graph out of all the function applications
toDot :: Operations -> Dot

-- | Update a map classifying values by type
countValueTypes :: Value -> DotState ()

-- | A DOT edge representing the dependency between 2 values
toDotEdge :: ValuesByType -> (Value, Value) -> Text

-- | Represent a value as a vertex in a dot graph we use some state to keep
--   track of values of the same type The values are numbered starting from
--   1 when there are several of them for the same type
toDotVertex :: ValuesByType -> Value -> Text

-- | Return the hash of a value based on its dependencies
hashOf :: Value -> Int

-- | Description of a Value in the DOT graph
nodeDescription :: ValueDescription -> ValueCounter -> Text

-- | Don't show the counter if there
showValueCounter :: ValueCounter -> Text

-- | We need to process the node descriptions - we add quotes arountd the
--   text - we remove quotes (") inside the text - we escape newlines
adjust :: Text -> Text

-- | Remove quotes from a textual description to avoid breaking the DOT
--   format
removeQuotes :: Text -> Text

-- | Replace n with \n so that newlines are kept in node descriptions
escapeNewlines :: Text -> Text
instance GHC.Show.Show Data.Registry.Internal.Dot.Dot
instance GHC.Classes.Eq Data.Registry.Internal.Dot.Dot


-- | This code is taken from
--   <a>https://stackoverflow.com/questions/28003135/is-it-possible-to-encode-a-generic-lift-function-in-haskell</a>
--   
--   to allow a generic lift operation over an <a>Applicative</a> context
--   So if you have a function: <tt>Int -&gt; Text -&gt; IO Int</tt>, it
--   can be lifted to have all of its parameters in <a>IO</a>:
--   
--   <pre>
--   f :: Int -&gt; Text -&gt; IO Int
--   
--   lifted :: IO Int -&gt; IO Text -&gt; IO Int
--   lifted = to @IO f
--   </pre>
module Data.Registry.Lift

-- | Typeclass for lifting pure functions to effectful arguments and
--   results
class Applicative f => ApplyVariadic f a b
applyVariadic :: ApplyVariadic f a b => f a -> b

-- | Lift a pure function to effectful arguments and results
allTo :: forall f a b. ApplyVariadic f a b => a -> b

-- | Typeclass for lifting impure functions to effectful arguments and
--   results
class Monad f => ApplyVariadic1 f a b
applyVariadic1 :: ApplyVariadic1 f a b => f a -> b

-- | Lift an effectful function to effectful arguments and results
argsTo :: forall f a b. ApplyVariadic1 f a b => a -> b

-- | Typeclass for lifting a function with a result of type m b into a
--   function with a result of type n b
class ApplyVariadic2 f g a b
applyVariadic2 :: ApplyVariadic2 f g a b => (forall x. f x -> g x) -> a -> b

-- | Lift a function returning an effectful result to a function returning
--   another effectful result
outTo :: forall g f a b. ApplyVariadic2 f g a b => (forall x. f x -> g x) -> a -> b

-- | The output of some constructors can be "tagged" with a string to
--   indicate how a given value was built.
newtype Tag (s :: Symbol) a
Tag :: a -> Tag a
[unTag] :: Tag a -> a

-- | Tag a given constructor f with a string s. The <a>applyLast</a>
--   function only applies the tag to the output type of the constructor.
--   For example data Salary = Fixed Int | Variable Int Double tag
--   @<a>Variable</a> Variable :: Int -&gt; Double -&gt; Tag
--   <a>Variable</a> Salary
tag :: forall (s :: Symbol) fun. CNumArgs (CountArgs fun) fun => fun -> Apply (Tag s) (CountArgs fun) fun

-- | ApplyLast typeclass provided by @neongreen It uses an auxiliary
--   typeclass to count the arguments of a function
data Nat
Z :: Nat
S :: Nat -> Nat
data NumArgs :: Nat -> * -> *
[NAZ] :: NumArgs Z a
[NAS] :: NumArgs n b -> NumArgs (S n) (a -> b)
type family CountArgs (f :: *) :: Nat
class CNumArgs (numArgs :: Nat) (arrows :: *)
getNA :: CNumArgs numArgs arrows => NumArgs numArgs arrows
type family Apply (f :: * -> *) (n :: Nat) (arrows :: *) :: *
applyLast :: forall f fun. (Applicative f, CNumArgs (CountArgs fun) fun) => fun -> Apply f (CountArgs fun) fun
applyLast' :: forall f n fun. Applicative f => NumArgs n fun -> fun -> Apply f n fun
instance GHC.Show.Show a => GHC.Show.Show (Data.Registry.Lift.Tag s a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Registry.Lift.Tag s a)
instance Data.Registry.Lift.CNumArgs 'Data.Registry.Lift.Z a
instance Data.Registry.Lift.CNumArgs n b => Data.Registry.Lift.CNumArgs ('Data.Registry.Lift.S n) (a -> b)
instance GHC.Base.Functor (Data.Registry.Lift.Tag s)
instance GHC.Base.Applicative (Data.Registry.Lift.Tag s)
instance (b Data.Type.Equality.~ g a) => Data.Registry.Lift.ApplyVariadic2 f g (f a) b
instance (Data.Registry.Lift.ApplyVariadic2 f g a' b', b Data.Type.Equality.~ (a -> b')) => Data.Registry.Lift.ApplyVariadic2 f g (a -> a') b
instance (GHC.Base.Monad f, b Data.Type.Equality.~ f a) => Data.Registry.Lift.ApplyVariadic1 f (f a) b
instance (GHC.Base.Monad f, Data.Registry.Lift.ApplyVariadic1 f a' b', b Data.Type.Equality.~ (f a -> b')) => Data.Registry.Lift.ApplyVariadic1 f (a -> a') b
instance (GHC.Base.Applicative f, b Data.Type.Equality.~ f a) => Data.Registry.Lift.ApplyVariadic f a b
instance (GHC.Base.Applicative f, Data.Registry.Lift.ApplyVariadic f a' b', b Data.Type.Equality.~ (f a -> b')) => Data.Registry.Lift.ApplyVariadic f (a -> a') b


-- | Type level functions to statically assess if a value can be built out
--   of a Registry
--   
--   For now we don't check if there could be cycles in the registry
--   functions
module Data.Registry.Solver

-- | Compute the list of input types for a function
type family Inputs f :: [*]

-- | Compute the output type for a function
type family Output f :: *

-- | Compute if a type is contained in a list of types
type family Contains (a :: *) (els :: [*]) :: Constraint

-- | Shorthand type alias when many such constraints need to be added to a
--   type signature
type out :- a = Contains a out

-- | Compute if each element of a list of types is contained in another
--   list
class IsSubset (ins :: [*]) (out :: [*])

-- | From the list of all the input types and outputs types of a registry
--   Can we create all the output types?
class Solvable (ins :: [*]) (out :: [*])

-- | Extracted from the typelevel-sets project and adapted for the Registry
--   datatype This union deduplicates elements only if they appear in
--   contiguously What we really want is typelevel sets but they are too
--   slow for now
--   <a>https://github.com/dorchard/type-level-sets/issues/17</a>
type family (:++) (x :: [k]) (y :: [k]) :: [k]
instance Data.Registry.Solver.IsSubset ins out => Data.Registry.Solver.Solvable ins out
instance Data.Registry.Solver.IsSubset '[] out
instance (Data.Registry.Solver.Contains a out, Data.Registry.Solver.IsSubset els out) => Data.Registry.Solver.IsSubset (a : els) out


-- | A registry supports the creation of values out of existing values and
--   functions.
--   
--   It contains 4 parts:
--   
--   <ul>
--   <li>values: they are available for building anything else and have
--   their exact value can be shown</li>
--   <li>functions: they are used to build other values. Only their type
--   can be shown</li>
--   <li>specializations: description of specific values to use while
--   trying to build another value of a given type</li>
--   <li>modifiers: function to apply to a newly built value before storing
--   it for future use</li>
--   </ul>
--   
--   A registry is created by using the <a>+:</a> operator, adding
--   functions or values to the empty <a>end</a> registry:
--   
--   <pre>
--   registry =
--        val (Config 1)
--     +: val "hello"
--     +: fun add1
--     +: fun show1
--     +: end
--   </pre>
--   
--   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 <a>&lt;+&gt;</a> operator to "override" some
--   configurations:
--   
--   <pre>
--   mocks =
--        fun noLogging
--     +: fun inMemoryDb
--     +: end
--   
--   mocks &lt;+&gt; registry
--   </pre>
module Data.Registry.Registry

-- | Container for a list of functions or values Internally all functions
--   and values are stored as <a>Dynamic</a> values so that we can access
--   their representation
data Registry (inputs :: [*]) (outputs :: [*])
Registry :: Values -> Functions -> Specializations -> Modifiers -> Registry
[_values] :: Registry -> Values
[_functions] :: Registry -> Functions
[_specializations] :: Registry -> Specializations
[_modifiers] :: Registry -> Modifiers

-- | Append 2 registries together
(<+>) :: Registry is1 os1 -> Registry is2 os2 -> Registry (is1 :++ is2) (os1 :++ os2)

-- | Store an element in the registry Internally elements are stored as
--   <a>Dynamic</a> values
register :: Typeable a => Typed a -> Registry ins out -> Registry (Inputs a :++ ins) (Output a : out)

-- | Add an element to the Registry - Alternative to register where the
--   parentheses can be ommitted
(+:) :: Typeable a => Typed a -> Registry ins out -> Registry (Inputs a :++ ins) (Output a : out)
infixr 5 +:

-- | The empty Registry
end :: Registry '[] '[]

-- | Create a value which can be added to the <a>Registry</a>
val :: (Typeable a, Show a) => a -> Typed a

-- | Create a value which can be added to the <a>Registry</a> and "lift" it
--   to an <a>Applicative</a> context
valTo :: forall m a. (Applicative m, Typeable a, Typeable (m a), Show a) => a -> Typed (m a)

-- | Create a "lifted" a Value
liftProvidedValue :: forall m a. (Applicative m, Typeable a, Typeable (m a), Show a) => a -> Value

-- | Create a function which can be added to the <a>Registry</a>
fun :: Typeable a => a -> Typed a

-- | This is a shortcut to <tt>fun . allTo</tt> where <tt>allTo</tt> lifts
--   all the inputs and output to an <a>Applicative</a> context
funTo :: forall m a b. (ApplyVariadic m a b, Typeable a, Typeable b) => a -> Typed b

-- | This is a shortcut to <tt>fun . argsTo</tt> where <tt>allTo</tt> lifts
--   all the inputs to an Applicative context
funAs :: forall m a b. (ApplyVariadic1 m a b, Typeable a, Typeable b) => a -> Typed b

-- | For a given type <tt>a</tt> being currently built when a value of type
--   <tt>b</tt> is required pass a specific value
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

-- | This is similar to specialize but additionally uses the <a>Show</a>
--   instance of <tt>b</tt> to display more information when printing the
--   registry 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

-- | For a given type <tt>a</tt> being currently built when a value of type
--   <tt>b</tt> is required pass a specific value
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

-- | Typeclass for extracting type representations out of a list of types
class PathToTypeReps (path :: [*])
someTypeReps :: PathToTypeReps path => Proxy path -> NonEmpty SomeTypeRep

-- | Once a value has been computed allow to modify it before storing it
--   This keeps the same registry type
tweak :: forall a ins out. (Typeable a, Contains a out) => (a -> a) -> Registry ins out -> Registry ins out

-- | Once a value has been computed allow to modify it before storing it
tweakUnsafe :: forall a ins out. Typeable a => (a -> a) -> Registry ins out -> Registry ins out

-- | 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 <a>IO</a> because we are caching a value and this is a
--   side-effect!
memoize :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a), Contains (m a) out) => Registry ins out -> IO (Registry ins out)

-- | Memoize an action for a given type but don't check if the value is
--   part of the registry outputs
memoizeUnsafe :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a)) => Registry ins out -> IO (Registry ins out)

-- | Memoize *all* the output actions of a Registry when they are creating
--   effectful components This relies on a helper data structure
--   <a>MemoizeRegistry</a> tracking the types already memoized and a
--   typeclass MemoizedActions going through the list of <tt>out</tt> types
--   to process them one by one. Note that a type of the form <tt>a</tt>
--   will not be memoized (only `m a`)
memoizeAll :: forall m ins out. (MonadIO m, MemoizedActions out) => Registry ins out -> IO (Registry ins out)
newtype MemoizeRegistry (todo :: [*]) (ins :: [*]) (out :: [*])
MemoizeRegistry :: Registry ins out -> MemoizeRegistry
[_unMemoizeRegistry] :: MemoizeRegistry -> 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
memoizeActions :: MemoizedActions ls => MemoizeRegistry ls ins out -> IO (MemoizeRegistry '[] ins out)

-- | <i>Deprecated: use memoize instead</i>
singleton :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a), Contains (m a) out) => Registry ins out -> IO (Registry ins out)

-- | <i>Deprecated: use memoizeUnsafe instead</i>
singletonUnsafe :: forall m a ins out. (MonadIO m, Typeable a, Typeable (m a)) => Registry ins out -> IO (Registry ins out)
instance Data.Registry.Registry.MemoizedActions '[]
instance (Control.Monad.IO.Class.MonadIO m, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable (m a), Data.Registry.Registry.MemoizedActions rest) => Data.Registry.Registry.MemoizedActions (m a : rest)
instance Data.Registry.Registry.MemoizedActions rest => Data.Registry.Registry.MemoizedActions (a : rest)
instance Data.Typeable.Internal.Typeable a => Data.Registry.Registry.PathToTypeReps '[a]
instance (Data.Typeable.Internal.Typeable a, Data.Registry.Registry.PathToTypeReps rest) => Data.Registry.Registry.PathToTypeReps (a : rest)
instance GHC.Show.Show (Data.Registry.Registry.Registry inputs outputs)
instance GHC.Base.Semigroup (Data.Registry.Registry.Registry inputs outputs)
instance GHC.Base.Semigroup (Data.Registry.Registry.Registry inputs outputs) => GHC.Base.Monoid (Data.Registry.Registry.Registry inputs outputs)


-- | This module provides functions to make values out of a registry. The
--   general algorithm is the following
--   
--   <ol>
--   <li>for a given value type search in the existing list of values a
--   value with the same type. If found return it</li>
--   <li>if not found search a function having the desired output type if
--   found, now try to recursively make all the input parameters. Keep a
--   stack of the current types trying to be built.</li>
--   <li>when trying to make an input parameter if the current input type
--   is already in the types trying to be built then there is a cycle.
--   Return an error in that case</li>
--   <li>when a value has been constructed place it on top of the existing
--   value list so that it can be reused by other functions</li>
--   </ol>
module Data.Registry.Make

-- | For a given registry make an element of type a We want to ensure that
--   a is indeed one of the return types We also try to statically check if
--   there aren't other possible errors
make :: forall a ins out. (Typeable a, Contains a out, Solvable ins out) => Registry ins out -> a

-- | Same as make but without the solvable constraint to compile faster in
--   tests for example
makeFast :: forall a ins out. (Typeable a, Contains a out) => Registry ins out -> a

-- | This version of make only execute checks at runtime this can speed-up
--   compilation when writing tests or in ghci
makeEither :: forall a ins out. Typeable a => Registry ins out -> Either Text a

-- | This version of <a>make</a> only execute checks at runtime this can
--   speed-up compilation when writing tests or in ghci
makeUnsafe :: forall a ins out. Typeable a => Registry ins out -> a

module Data.Registry.Statistics
makeStatistics :: forall a ins out. (Typeable a, Contains a out, Solvable ins out) => Registry ins out -> Statistics
makeStatisticsFast :: forall a ins out. (Typeable a, Contains a out) => Registry ins out -> Statistics

-- | Return <a>Statistics</a> as the result of the creation of a value of a
--   given type
makeStatisticsEither :: forall a ins out. Typeable a => Registry ins out -> Either Text Statistics

-- | Return <a>Statistics</a> as the result of the creation of a value of a
--   given type (and throws an exception if the value cannot be created)
makeStatisticsUnsafe :: forall a ins out. Typeable a => Registry ins out -> Statistics


-- | This module provides functions to extract a DOT graph
--   (https:/<i>en.wikipedia.org</i>wiki/DOT_(graph_description_language)
--   out of a <a>Registry</a>.
module Data.Registry.Dot

-- | Make a DOT graph for a specific value <tt>a</tt> built from the
--   <a>Registry</a> <tt>a</tt> is at the root of the graph and its
--   children are values needed to build <tt>a</tt>
makeDot :: forall a ins out. (Typeable a, Contains a out, Solvable ins out) => Registry ins out -> Dot

-- | Similar to <tt>make</tt> but does not check if <tt>a</tt> can be made
--   out of the <tt>Regisry</tt> It returns a Left value if that's not the
--   case
makeDotEither :: forall a ins out. Typeable a => Registry ins out -> Either Text Dot

-- | Similar to <tt>make</tt> but does not check if <tt>a</tt> can be made
--   out of the Regisry You can use this version to get faster compilation
--   times
makeDotFast :: forall a ins out. (Typeable a, Contains a out) => Registry ins out -> Dot

-- | Similar to <tt>make</tt> but does not check if <tt>a</tt> can be made
--   out of the <tt>Regisry</tt> and throws an exception if that's not the
--   case
makeDotUnsafe :: forall a ins out. Typeable a => Registry ins out -> Dot


-- | This module contains data structures to describe the "warming-up" of
--   componnts in order to ensure that they are properly configured:
--   
--   <ul>
--   <li>createWarmup creates a warmup from an action returning a
--   <a>Result</a></li>
--   <li>warmupOf takes a component name and unit action then just checks
--   that the action executes without exception</li>
--   </ul>
module Data.Registry.Warmup

-- | A list of actions to run at startup
newtype Warmup
Warmup :: [IO Result] -> Warmup
[_warmUp] :: Warmup -> [IO Result]

-- | Create a warmup action for a given component The type of the component
--   is used as the description for the action to execute
warmupOf :: Typeable a => a -> IO () -> Warmup

-- | Create a <a>Warmup</a> from an <a>IO</a> action returning a
--   <a>Result</a>
createWarmup :: IO Result -> Warmup

-- | The empty <a>Warmup</a>
noWarmup :: Warmup

-- | Create a <a>Warmup</a> with no action but just the type of a component
declareWarmup :: Typeable a => a -> Warmup

-- | Result of a <a>Warmup</a>
data Result
Empty :: Result
Ok :: [Text] -> Result
Failed :: [Text] -> Result

-- | Return <a>True</a> if a <a>Warmup</a> was successful
isSuccess :: Result -> Bool

-- | Create a successful <a>Result</a>
ok :: Text -> Result

-- | Create a failed <a>Result</a>
failed :: Text -> Result

-- | Extract the list of all the messages from a <a>Result</a>
messages :: Result -> [Text]

-- | Simple sequential warmup strategy
runWarmup :: Warmup -> IO Result

-- | <a>runBoth</a> runs both tasks and cumulate the results exceptions are
--   being transformed into Failed results
runBoth :: IO Result -> IO Result -> IO Result
instance GHC.Base.Semigroup Data.Registry.Warmup.Warmup
instance GHC.Base.Monoid Data.Registry.Warmup.Warmup
instance GHC.Show.Show Data.Registry.Warmup.Result
instance GHC.Classes.Eq Data.Registry.Warmup.Result
instance GHC.Base.Monoid Data.Registry.Warmup.Result
instance GHC.Base.Semigroup Data.Registry.Warmup.Result


-- | RIO is equivalent to <tt>ResourceT (WriterT Warmup IO)</tt> It can be
--   used to instantiate "components as records of functions" where each
--   component can allocate resources and have a "warmup phase" to preload
--   data or assess if it is working properly.
module Data.Registry.RIO

-- | Data type encapsulating resource finalizers
newtype Stop
Stop :: InternalState -> Stop

-- | Run all finalizers
runStop :: Stop -> IO ()

-- | This newtype creates a monad to sequence component creation actions,
--   cumulating start/stop tasks found along the way
newtype RIO a
RIO :: (Stop -> IO (a, Warmup)) -> RIO a
[runRIO] :: RIO a -> Stop -> IO (a, Warmup)

-- | Use a RIO value and make sure that resources are closed Only run the
--   action if the warmup is successful
withRIO :: MonadIO m => RIO a -> (a -> IO ()) -> m Result

-- | This function must be used to run services involving a top component
--   It creates the top component and invokes all warmup functions
--   
--   The passed function <tt>f</tt> is used to decide whether to continue
--   or not depending on the Result
--   
--   We also make sure that all effects are memoized by calling
--   <a>memoizeAll</a> on the Registry here!
withRegistry :: forall a b ins out m. (Typeable a, Contains (RIO a) out, Solvable ins out, MonadIO m, MemoizedActions out) => Registry ins out -> (Result -> a -> IO b) -> m b

-- | This can be used if you want to insert the component creation inside
--   another action managed with <a>ResourceT</a>. Or if you want to call
--   <a>runResourceT</a> yourself later
runRegistryT :: forall a ins out m. (Typeable a, Contains (RIO a) out, Solvable ins out, MonadIO m, MemoizedActions out) => Registry ins out -> ResourceT m (a, Warmup)

-- | Use a RIO value and make sure that resources are closed Don't run the
--   warmup
withNoWarmupRIO :: MonadIO m => RIO a -> (a -> IO b) -> m b

-- | Use a RIO value and make sure that resources are closed Run the warmup
--   but ignore the result
withRIOIgnoreWarmupResult :: MonadIO m => RIO a -> (a -> IO b) -> m b

-- | Use a RIO value and make sure that resources are closed Run a unit
--   function with the warmup result (print or throw exception)
withRIOAndWarmupResult :: MonadIO m => (Result -> IO ()) -> RIO a -> (a -> IO b) -> m b

-- | Instantiate the component but don't execute the warmup (it may take
--   time) and keep the Stop value to clean resources later This function
--   statically checks that the component can be instantiated
executeRegistry :: forall a ins out m. (Typeable a, Contains (RIO a) out, Solvable ins out, MonadIO m) => Registry ins out -> m (a, Warmup, Stop)

-- | Instantiate the component but don't execute the warmup (it may take
--   time) and lose a way to cleanu up resources | Almost no compilation
--   time is spent on checking that component resolution is possible
unsafeRun :: forall a ins out m. (Typeable a, Contains (RIO a) out, MonadIO m) => Registry ins out -> m a

-- | Instantiate the component but don't execute the warmup (it may take
--   time) and lose a way to cleanu up resources Don't even check that a
--   component can be built out of the registry
unsafeRunDynamic :: forall a ins out m. (Typeable a, MonadIO m) => Registry ins out -> m a

-- | Same as <a>unsafeRun</a> but keep the <a>Stop</a> value to be able to
--   clean resources later
unsafeRunWithStop :: forall a ins out m. (Typeable a, Contains (RIO a) out, MonadIO m) => Registry ins out -> m (a, Stop)
unsafeRunDynamicWithStop :: forall a ins out m. (Typeable a, MonadIO m) => Registry ins out -> m (a, Stop)

-- | Lift a <a>Warmup</a> action into the <a>RIO</a> monad
warmupWith :: Warmup -> RIO ()

-- | Allocate some resource
allocate :: IO a -> (a -> IO ()) -> RIO a
instance GHC.Base.Functor Data.Registry.RIO.RIO
instance GHC.Base.Applicative Data.Registry.RIO.RIO
instance GHC.Base.Monad Data.Registry.RIO.RIO
instance Control.Monad.IO.Class.MonadIO Data.Registry.RIO.RIO
instance Control.Monad.Catch.MonadThrow Data.Registry.RIO.RIO
instance Control.Monad.Base.MonadBase GHC.Types.IO Data.Registry.RIO.RIO
instance Control.Monad.Trans.Resource.Internal.MonadResource Data.Registry.RIO.RIO
instance GHC.Base.Alternative Data.Registry.RIO.RIO
instance Data.Functor.Alt.Alt Data.Registry.RIO.RIO


-- | Import this module if you want to access all the functionalities of
--   the Registry API
module Data.Registry
