packages feed

registry 0.4.0.0 → 0.5.0.0

raw patch · 12 files changed

+195/−145 lines, 12 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Registry.Internal.Types: Functions :: MultiMap SomeTypeRep Function -> Functions
- Data.Registry.Internal.Types: addFunction :: Function -> Functions -> Functions
- Data.Registry.Internal.Types: appendFunction :: Function -> Functions -> Functions
- Data.Registry.Internal.Types: findFunction :: SomeTypeRep -> Functions -> Maybe Function
- Data.Registry.Internal.Types: fromFunctions :: [Function] -> Functions
- Data.Registry.Internal.Types: instance GHC.Base.Monoid Data.Registry.Internal.Types.Functions
- Data.Registry.Internal.Types: instance GHC.Base.Semigroup Data.Registry.Internal.Types.Functions
- Data.Registry.Internal.Types: instance GHC.Show.Show Data.Registry.Internal.Types.Functions
- Data.Registry.Internal.Types: newtype Functions
- Data.Registry.Registry: [_functions] :: Registry (inputs :: [Type]) (outputs :: [Type]) -> Functions
- Data.Registry.Registry: [_values] :: Registry (inputs :: [Type]) (outputs :: [Type]) -> Values
+ Data.Registry.Internal.Types: Entries :: MultiMap SomeTypeRep Untyped -> Entries
+ Data.Registry.Internal.Types: addEntry :: Typed a -> Entries -> Entries
+ Data.Registry.Internal.Types: addUntyped :: Untyped -> Entries -> Entries
+ Data.Registry.Internal.Types: appendEntry :: Typed a -> Entries -> Entries
+ Data.Registry.Internal.Types: appendUntyped :: Untyped -> Entries -> Entries
+ Data.Registry.Internal.Types: findUntyped :: SomeTypeRep -> Entries -> Maybe Untyped
+ Data.Registry.Internal.Types: findValue :: SomeTypeRep -> Values -> Maybe Value
+ Data.Registry.Internal.Types: fromUntyped :: [Untyped] -> Entries
+ Data.Registry.Internal.Types: instance GHC.Base.Monoid Data.Registry.Internal.Types.Entries
+ Data.Registry.Internal.Types: instance GHC.Base.Semigroup Data.Registry.Internal.Types.Entries
+ Data.Registry.Internal.Types: instance GHC.Show.Show Data.Registry.Internal.Types.Entries
+ Data.Registry.Internal.Types: listValues :: Values -> [Value]
+ Data.Registry.Internal.Types: newtype Entries
+ Data.Registry.Internal.Types: outTypeRep :: Untyped -> SomeTypeRep
+ Data.Registry.Internal.Types: untypedDyn :: Untyped -> Dynamic
+ Data.Registry.Registry: [_entries] :: Registry (inputs :: [Type]) (outputs :: [Type]) -> Entries
- Data.Registry.Internal.Make: makeInputs :: Function -> [SomeTypeRep] -> Context -> Functions -> Specializations -> Modifiers -> Stack [Value]
+ Data.Registry.Internal.Make: makeInputs :: Function -> [SomeTypeRep] -> Context -> Entries -> Specializations -> Modifiers -> Stack [Value]
- Data.Registry.Internal.Make: makeUntyped :: SomeTypeRep -> Context -> Functions -> Specializations -> Modifiers -> Stack (Maybe Value)
+ Data.Registry.Internal.Make: makeUntyped :: SomeTypeRep -> Context -> Entries -> Specializations -> Modifiers -> Stack (Maybe Value)
- Data.Registry.Internal.Types: [unFunctions] :: Functions -> MultiMap SomeTypeRep Function
+ Data.Registry.Internal.Types: [unFunctions] :: Entries -> MultiMap SomeTypeRep Untyped
- Data.Registry.Internal.Types: describeFunctions :: Functions -> Text
+ Data.Registry.Internal.Types: describeFunctions :: Entries -> Text
- Data.Registry.Internal.Types: describeValues :: Values -> Text
+ Data.Registry.Internal.Types: describeValues :: Entries -> Text
- Data.Registry.Internal.Types: toFunctions :: Functions -> [Function]
+ Data.Registry.Internal.Types: toFunctions :: Entries -> [Function]
- Data.Registry.Internal.Types: toValues :: Values -> [Value]
+ Data.Registry.Internal.Types: toValues :: Entries -> [Value]
- Data.Registry.Registry: Registry :: Values -> Functions -> Specializations -> Modifiers -> Registry (inputs :: [Type]) (outputs :: [Type])
+ Data.Registry.Registry: Registry :: Entries -> Specializations -> Modifiers -> Registry (inputs :: [Type]) (outputs :: [Type])

Files

registry.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: d44a2153bfc290f93fe7c376691bb652a7638881f01e9c65797b4610dd06da67+-- hash: f5f64917e56100dee68b1a07abc7a53b5e323440dfeb36623410f015fb2129c5  name:           registry-version:        0.4.0.0+version:        0.5.0.0 synopsis:       data structure for assembling components description:    This library provides a "Registry" which is a data structure containing a list of functions and values representing dependencies in a directed acyclic graph. A `make` function can then be used to create a value of a specific type out of the registry.                 You can start with the [README](https://github.com/etorreborre/registry/blob/master/README.md) for a full description of the library.
src/Data/Registry/Internal/Make.hs view
@@ -27,11 +27,11 @@ -- | Make a value from a desired output type represented by SomeTypeRep --   and a list of possible constructors --   A 'Context' 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+--  Entries 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)-makeUntyped targetType context functions specializations modifiers = do+makeUntyped :: SomeTypeRep -> Context -> Entries -> Specializations -> Modifiers -> Stack (Maybe Value)+makeUntyped targetType context entries specializations modifiers = do   values <- getValues   -- is there already a value with the desired type? Or a specialization   let foundValue = findValueOrSpecialization targetType context specializations values@@ -47,9 +47,8 @@     Just (Left specialization) -> do       -- if the specialization is just a value, return it       case createValueFromSpecialization context specialization of-        UntypedValue v -> do-          modified <- storeValue modifiers v-          pure (Just modified)+        UntypedValue v ->+          Just <$> storeValue modifiers v         UntypedFunction f -> do           -- we don't fail the building if a specialization cannot be applied           -- we try to use an already created value or build one from scratch@@ -61,7 +60,7 @@     makeWithConstructor :: Stack (Maybe Value)     makeWithConstructor = do       -- if not, is there a way to build such value?-      case findFunction targetType functions of+      case findUntyped targetType entries of         Nothing ->           lift $             Left $@@ -69,13 +68,15 @@                 <> T.intercalate "\nrequiring " (showContextTargets context)                 <> "\n\nNo constructor was found for "                 <> showSingleType targetType-        Just f ->+        Just (UntypedFunction f) ->           makeWithFunction f Nothing+        Just (UntypedValue v) ->+          Just <$> storeValue modifiers v      makeWithFunction :: Function -> Maybe Specialization -> Stack (Maybe Value)     makeWithFunction f mSpecialization = do       let inputTypes = collectInputTypes f-      inputs <- makeInputs f inputTypes context functions specializations modifiers+      inputs <- makeInputs f inputTypes context entries specializations modifiers        if length inputs /= length inputTypes         then do@@ -124,15 +125,15 @@   [SomeTypeRep] ->   -- | current context of types being built   Context ->-  -- | available functions to build values-  Functions ->+  -- | available entries to build values+  Entries ->   -- | list of values to use when in a specific context   Specializations ->   -- | modifiers to apply before storing made values   Modifiers ->   Stack [Value] -- list of made values makeInputs _ [] _ _ _ _ = pure []-makeInputs function (i : ins) c@(Context context) functions specializations modifiers =+makeInputs function (i : ins) c@(Context context) entries specializations modifiers =   if i `elem` contextTypes c     then       lift $@@ -143,11 +144,11 @@                 <> (show <$> context)                 <> ["But we are trying to build again " <> show i]     else do-      madeInput <- makeUntyped i (Context ((i, Just (funDynTypeRep function)) : context)) functions specializations modifiers+      madeInput <- makeUntyped i (Context ((i, Just (funDynTypeRep function)) : context)) entries specializations modifiers       case madeInput of         Nothing ->           -- if one input cannot be made, iterate with the rest for better reporting           -- of what could be eventually made-          makeInputs function ins (Context context) functions specializations modifiers+          makeInputs function ins (Context context) entries specializations modifiers         Just v ->-          (v :) <$> makeInputs function ins (Context context) functions specializations modifiers+          (v :) <$> makeInputs function ins (Context context) entries specializations modifiers
src/Data/Registry/Internal/Statistics.hs view
@@ -50,7 +50,7 @@ -- | Return the specializations used during the creation of values valuesSpecializations :: Statistics -> [Specialization] valuesSpecializations stats =-  case toValues (values stats) of+  case listValues (values stats) of     [] -> []     v : vs ->       case valueSpecialization v of@@ -63,7 +63,7 @@ --   specialization allValuesPaths :: Statistics -> Paths allValuesPaths stats = do-  v <- toValues $ values stats+  v <- listValues $ values stats   valuePaths v  -- | Return all the paths from a given value to all its dependencies@@ -75,8 +75,8 @@  -- | Find the most recently created value of a given type findMostRecentValue :: forall a. (Typeable a) => Statistics -> Maybe Value-findMostRecentValue stats = find (\v -> valueDynTypeRep v == someTypeRep (Proxy :: Proxy a)) $ toValues (values stats)+findMostRecentValue stats = findValue (someTypeRep (Proxy :: Proxy a)) (values stats)  -- | Find the created values of a given type findCreatedValues :: forall a. (Typeable a) => Statistics -> [Value]-findCreatedValues stats = filter (\v -> valueDynTypeRep v == someTypeRep (Proxy :: Proxy a)) $ toValues (values stats)+findCreatedValues stats = findValues(someTypeRep (Proxy :: Proxy a)) (values stats)
src/Data/Registry/Internal/Types.hs view
@@ -208,7 +208,7 @@   | TypedFunction Function  -- | A Untyped is used for storing either a value or a function---   in a specialization+--   in the registry data Untyped   = UntypedValue Value   | UntypedFunction Function@@ -219,78 +219,85 @@ untype (TypedValue v) = UntypedValue v untype (TypedFunction f) = UntypedFunction f --- | This is a list of functions (or "constructors") available for constructing values---   They are sorted by output type and if there are several available functions---   for a given type the first function in the list has the highest priority-newtype Functions = Functions-  { unFunctions :: MultiMap SomeTypeRep Function+-- | Return the output type of an untyped entry+outTypeRep :: Untyped -> SomeTypeRep+outTypeRep (UntypedValue v) = valueDynTypeRep v+outTypeRep (UntypedFunction f) = funDynOutTypeRep f++-- | Dynamic representation of a 'Function'+untypedDyn :: Untyped -> Dynamic+untypedDyn (UntypedFunction f) = funDyn f+untypedDyn (UntypedValue v) = valueDyn v+++-- | This is a list of entries in the registry available for constructing values+--   They are sorted by output type and if there are several available functions or values+--   for a given type the first one in the list has the highest priority+newtype Entries = Entries+  { unFunctions :: MultiMap SomeTypeRep Untyped   }   deriving (Show, Semigroup, Monoid) --- | Create a Functions data structure from a list of functions-fromFunctions :: [Function] -> Functions-fromFunctions fs = Functions (MM.fromList $ (\f -> (funDynOutTypeRep f, f)) <$> fs)+-- | Create a Entries data structure from a list of untyped entries+fromUntyped :: [Untyped] -> Entries+fromUntyped us = Entries (MM.fromList $ (\u -> (outTypeRep u, u)) <$> us) --- | Create a list of functions from the Functions data structure-toFunctions :: Functions -> [Function]-toFunctions (Functions fs) = snd <$> MM.toList fs+-- | Create a list of functions from the Entries data structure+toFunctions :: Entries -> [Function]+toFunctions (Entries es) = mapMaybe (getFunction . snd) (MM.toList es)+  where+    getFunction = \case+      UntypedFunction f -> Just f+      _ -> Nothing +-- | Create a list of values from the Entries data structure+toValues :: Entries -> [Value]+toValues (Entries es) = mapMaybe (getValue . snd) (MM.toList es)+  where+    getValue = \case+      UntypedValue v -> Just v+      _ -> Nothing+ -- | Display a list of constructors-describeFunctions :: Functions -> Text-describeFunctions functions@(Functions fs) =-  if MM.null fs+describeFunctions :: Entries -> Text+describeFunctions entries@(Entries es) =+  if MM.null es     then ""-    else unlines (funDescriptionToText . funDescription <$> toFunctions functions)+    else unlines (funDescriptionToText . funDescription <$> toFunctions entries) --- | Add one more Function to the list of Functions.+-- | Display a list of values+describeValues :: Entries -> Text+describeValues entries@(Entries es) =+  if MM.null es+    then ""+    else unlines (valDescriptionToText . valDescription <$> toValues entries)++-- | Add one more Function to the list of Entries. --   It gets the highest priority for functions with the same output type-addFunction :: Function -> Functions -> Functions-addFunction f (Functions fs) = Functions (MM.insert (funDynOutTypeRep f) f fs)+addUntyped :: Untyped -> Entries -> Entries+addUntyped e (Entries es) = Entries (MM.insert (outTypeRep e) e es) --- | Add one more Function to the list of Functions+-- | Add an entry to the list of Entries.+--   It gets the highest priority for functions with the same output type+addEntry :: Typed a -> Entries -> Entries+addEntry e = addUntyped (untype e)++-- | Add one more untyped entry to the list of Entries --   It gets the lowest priority for functions with the same output type --   This is not a very efficient because it requires a full recreation of the map-appendFunction :: Function -> Functions -> Functions-appendFunction f (Functions fs) = Functions (MM.fromList $ MM.toList fs <> [(funDynOutTypeRep f, f)])---- | Find a constructor function returning a target type---   from a list of constructors-findFunction :: SomeTypeRep -> Functions -> Maybe Function-findFunction target (Functions fs) = P.head $ MM.lookup target fs---- | List of values available which can be used as parameters to---   constructors for building other values-newtype Values = Values {unValues :: MultiMap SomeTypeRep Value} deriving (Show, Semigroup, Monoid)---- | Create a Values data structure from a list of values-fromValues :: [Value] -> Values-fromValues vs = Values (MM.fromList $ (\v -> (valueDynTypeRep v, v)) <$> vs)---- | Create a list of values from the Values data structure-toValues :: Values -> [Value]-toValues (Values vs) = snd <$> MM.toList vs---- | Display a list of values-describeValues :: Values -> Text-describeValues values@(Values vs) =-  if MM.null vs-    then ""-    else unlines (valDescriptionToText . valDescription <$> toValues values)---- | Add one more Value to the list of Values-addValue :: Value -> Values -> Values-addValue v (Values vs) = Values (MM.insert (valueDynTypeRep v) v vs)+appendUntyped :: Untyped -> Entries -> Entries+appendUntyped u (Entries es) = Entries (MM.fromList $ MM.toList es <> [(outTypeRep u, u)]) --- | Add one more Value to the list of Values---   It gets the lowest priority for values with the same type+-- | Add one more untyped entry to the list of Entries+--   It gets the lowest priority for functions with the same output type --   This is not a very efficient because it requires a full recreation of the map-appendValue :: Value -> Values -> Values-appendValue v (Values vs) = Values (MM.fromList $ MM.toList vs <> [(valueDynTypeRep v, v)])+appendEntry :: Typed a -> Entries -> Entries+appendEntry e = appendUntyped (untype e) --- | Find all the values with a specific type---   from a list of constructors-findValues :: SomeTypeRep -> Values -> [Value]-findValues target (Values vs) = MM.lookup target vs+-- | Find a function or value returning a target type+--   from a list of entries+findUntyped :: SomeTypeRep -> Entries -> Maybe Untyped+findUntyped target (Entries es) = P.head $ MM.lookup target es  -- | The types of values that we are trying to build at a given moment --   of the resolution algorithm.@@ -486,3 +493,38 @@   if P.null ms     then ""     else "modifiers for types\n" <> unlines (P.show . fst <$> ms)+++-- * VALUES++-- | List of values available which can be used as parameters to+--   constructors for building other values+newtype Values = Values {unValues :: MultiMap SomeTypeRep Value} deriving (Show, Semigroup, Monoid)++-- | Create a Values data structure from a list of values+fromValues :: [Value] -> Values+fromValues vs = Values (MM.fromList $ (\v -> (valueDynTypeRep v, v)) <$> vs)++-- | Return values as a list+listValues :: Values -> [Value]+listValues (Values vs) = snd <$> MM.toList vs++-- | Add one more Value to the list of Values+addValue :: Value -> Values -> Values+addValue v (Values vs) = Values (MM.insert (valueDynTypeRep v) v vs)++-- | Add one more Value to the list of Values+--   It gets the lowest priority for values with the same type+--   This is not a very efficient because it requires a full recreation of the map+appendValue :: Value -> Values -> Values+appendValue v (Values vs) = Values (MM.fromList $ MM.toList vs <> [(valueDynTypeRep v, v)])++-- | Find all the values with a specific type+--   from a list of values+findValues :: SomeTypeRep -> Values -> [Value]+findValues target (Values vs) = MM.lookup target vs++-- | Find the first value with a specific type+--   from a list of values+findValue :: SomeTypeRep -> Values -> Maybe Value+findValue target = P.head . findValues target
src/Data/Registry/Make.hs view
@@ -83,8 +83,8 @@ --   this can speed-up compilation when writing tests or in ghci makeEitherWithContext :: forall a ins out. (Typeable a) => Context -> Registry ins out -> Either Text a makeEitherWithContext context registry = do-  let values = _values registry-  let functions = _functions registry+  let values = mempty+  let entries = _entries registry   let specializations = _specializations registry   let modifiers = _modifiers registry   let targetType = someTypeRep (Proxy :: Proxy a)@@ -92,7 +92,7 @@   --  the list of values is kept as some State so that newly created values can be added to the current state   case runStackWithValues     values-    (makeUntyped targetType context functions specializations modifiers) of+    (makeUntyped targetType context entries specializations modifiers) of     Left e ->       Left . showRegistry $         "\nCould not create a "@@ -112,7 +112,7 @@   where     showRegistry message = do       let r = show registry-      -- this allows the display of registries of no more than ~ 30 functions+      -- this allows the display of registries of no more than ~ 30 entries       -- which should fit on a laptop screen       if (length . T.lines $ r) <= 35         then@@ -121,7 +121,7 @@             <> r             <> "=====================\n"             <> message-            <> "\n\nYou can check the registry displayed above the ===== line to verify the current values and functions\n"+            <> "\n\nYou can check the registry displayed above the ===== line to verify the current values and entries\n"         else           message             <> "\n\n (the registry is not displayed because it is too large)"
src/Data/Registry/Registry.hs view
@@ -7,10 +7,9 @@ -- | --  A registry supports the creation of values out of existing values and functions. -----  It contains 4 parts:+--  It contains 3 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+--  * entries: they can be either values or functions used to create values --  * 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 --@@ -50,19 +49,18 @@ --   Internally all functions and values are stored as 'Dynamic' values --   so that we can access their representation data Registry (inputs :: [Type]) (outputs :: [Type]) = Registry-  { _values :: Values,-    _functions :: Functions,+  { _entries :: Entries,     _specializations :: Specializations,     _modifiers :: Modifiers   }  instance Show (Registry inputs outputs) where-  show (Registry vs fs ss@(Specializations ss') ms@(Modifiers ms')) =+  show (Registry es ss@(Specializations ss') ms@(Modifiers ms')) =     toS . unlines $       [ "Values\n",-        describeValues vs,+        describeValues es,         "Constructors\n",-        describeFunctions fs+        describeFunctions es       ]         <> ( if not (null ss')                then@@ -80,19 +78,19 @@            )  instance Semigroup (Registry inputs outputs) where-  (<>) (Registry vs1 fs1 ss1 ms1) (Registry vs2 fs2 ss2 ms2) =-      Registry (vs1 <> vs2) (fs1 <> fs2) (ss1 <> ss2) (ms1 <> ms2)+  (<>) (Registry fs1 ss1 ms1) (Registry fs2 ss2 ms2) =+      Registry (fs1 <> fs2) (ss1 <> ss2) (ms1 <> ms2)  instance Semigroup (Registry inputs outputs) => Monoid (Registry inputs outputs) where-  mempty = Registry mempty mempty mempty mempty+  mempty = Registry mempty mempty mempty   mappend = (<>)  -- | Append 2 registries together infixr 4 <+>  (<+>) :: Registry is1 os1 -> Registry is2 os2 -> Registry (is1 :++ is2) (os1 :++ os2)-(<+>)(Registry vs1 fs1 ss1 ms1) (Registry vs2 fs2 ss2 ms2) =-      Registry (vs1 <> vs2) (fs1 <> fs2) (ss1 <> ss2) (ms1 <> ms2)+(<+>)(Registry fs1 ss1 ms1) (Registry fs2 ss2 ms2) =+      Registry (fs1 <> fs2) (ss1 <> ss2) (ms1 <> ms2)  -- | Store an element in the registry --   Internally elements are stored as 'Dynamic' values@@ -104,25 +102,18 @@ -- | Store an element in the registry --   Internally elements are stored as 'Dynamic' values registerUnchecked :: (Typeable a) => Typed a -> Registry ins out -> Registry (Inputs a :++ ins) (Output a ': out)-registerUnchecked (TypedValue v) (Registry values functions specializations modifiers) =-  Registry (addValue v values) functions specializations modifiers-registerUnchecked (TypedFunction f) (Registry values functions specializations modifiers) =-  Registry values (addFunction f functions) specializations modifiers+registerUnchecked t (Registry entries specializations modifiers) =+  Registry (addEntry t entries) specializations modifiers  -- | Store an element in the registry, at the end of the registry --   Internally elements are stored as 'Dynamic' values appendUnchecked :: (Typeable a) => Registry ins out -> Typed a -> Registry (ins :++ Inputs a) (out :++ '[Output a])-appendUnchecked (Registry values functions specializations modifiers) (TypedValue v) =-  Registry (appendValue v values) functions specializations modifiers-appendUnchecked (Registry values functions specializations modifiers) (TypedFunction f) =-  Registry values (appendFunction f functions) specializations modifiers+appendUnchecked (Registry entries specializations modifiers) t =+  Registry (appendEntry t entries) specializations modifiers  -- | Add 2 typed values together to form an initial registry addTypedUnchecked :: (Typeable a, Typeable b, ins ~ (Inputs a :++ Inputs b), out ~ '[Output a, Output b]) => Typed a -> Typed b -> Registry ins out-addTypedUnchecked (TypedValue v1) (TypedValue v2) = Registry (fromValues [v1, v2]) mempty mempty mempty-addTypedUnchecked (TypedValue v1) (TypedFunction f2) = Registry (fromValues [v1]) (fromFunctions [f2]) mempty mempty-addTypedUnchecked (TypedFunction f1) (TypedValue v2) = Registry (fromValues [v2]) (fromFunctions [f1]) mempty mempty-addTypedUnchecked (TypedFunction f1) (TypedFunction f2) = Registry mempty (fromFunctions [f1, f2]) mempty mempty+addTypedUnchecked t1 t2 = Registry (fromUntyped [untype t1, untype t2]) mempty mempty  -- | Add an element to the Registry but do not check that the inputs of a --   can already be produced by the registry@@ -191,13 +182,13 @@ -- | Make the lists of types in the Registry unique, either for better display --   or for faster compile-time resolution with the make function normalize :: Registry ins out -> Registry (Normalized ins) (Normalized out)-normalize (Registry vs fs ss ms) = Registry vs fs ss ms+normalize (Registry es ss ms) = Registry es ss ms  -- | Remove the parameters list of the registry and replace it with an empty type --   This makes it easier to read compilation errors where less types are being displayed --   On the other hand the resulting registry cannot be type-checked anymore when trying to get values out of it eraseTypes :: Registry ins out -> Registry '[ERASED_TYPES] '[ERASED_TYPES]-eraseTypes (Registry values functions specializations modifiers) = Registry values functions specializations modifiers+eraseTypes (Registry entries specializations modifiers) = Registry entries specializations modifiers  -- | Singleton type representing erased types data ERASED_TYPES@@ -206,15 +197,15 @@ --   for example with conditional like --     if True then fun myFunctionWithKnownOutputs <: r else r safeCoerce :: (IsSameSet out out1) => Registry ins out -> Registry ins1 out1-safeCoerce (Registry a b c d) = Registry a b c d+safeCoerce (Registry a b c) = Registry a b c  -- | And for extreme cases where you know you're doing the right thing but can't prove it unsafeCoerce :: Registry ins out -> Registry ins1 out1-unsafeCoerce (Registry a b c d) = Registry a b c d+unsafeCoerce (Registry a b c) = Registry a b c  -- | The empty Registry end :: Registry '[] '[]-end = Registry mempty mempty mempty mempty+end = Registry mempty mempty mempty  -- | Create a value which can be added to the Registry val :: (Typeable a, Show a) => a -> Typed a@@ -247,15 +238,15 @@ -- | For a given type a being currently built --   when a value of type b is required pass a specific value specialize :: forall a b ins out. (Typeable a) => Typed b -> Registry ins out -> Registry ins out-specialize b (Registry values functions (Specializations c) modifiers) = do+specialize b (Registry entries (Specializations c) modifiers) = do   let ss = Specializations (Specialization (pure $ someTypeRep (Proxy :: Proxy a)) (untype b) : c)-  Registry values functions ss modifiers+  Registry entries ss modifiers  -- | Specialize a function for a specific path of types specializePath :: forall path b ins out. (PathToTypeReps path) => Typed b -> Registry ins out -> Registry ins out-specializePath b (Registry values functions (Specializations c) modifiers) = do+specializePath b (Registry entries (Specializations c) modifiers) = do   let ss = Specializations (Specialization (someTypeReps (Proxy :: Proxy path)) (untype b) : c)-  Registry values functions ss modifiers+  Registry entries ss modifiers  -- | Typeclass for extracting type representations out of a list of types class PathToTypeReps (path :: [Type]) where@@ -270,10 +261,9 @@ -- | 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) => (a -> a) -> Registry ins out -> Registry ins out-tweak f (Registry values functions specializations (Modifiers mf)) =+tweak f (Registry entries specializations (Modifiers mf)) =   Registry-    values-    functions+    entries     specializations     (Modifiers ((someTypeRep (Proxy :: Proxy a), createConstModifierFunction f) : mf)) @@ -288,10 +278,10 @@ --   Note that the returned Registry is in 'IO' 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)) => Registry ins out -> IO (Registry ins out)-memoize (Registry values functions specializations (Modifiers mf)) = do+memoize (Registry entries specializations (Modifiers mf)) = do   cache <- newCache @a   let modifiers = Modifiers ((someTypeRep (Proxy :: Proxy (m a)), createFunction . fetch @a @m cache) : mf)-  pure $ Registry values functions specializations modifiers+  pure $ Registry entries specializations modifiers  -- | 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
src/Data/Registry/State.hs view
@@ -53,10 +53,8 @@  -- | Register modifications of elements which types are already in the registry addToRegistry :: (Typeable a, IsSubset (Inputs a) out a) => Typed a -> Registry ins out -> Registry ins out-addToRegistry (TypedValue v) (Registry values functions specializations modifiers) =-  Registry (addValue v values) functions specializations modifiers-addToRegistry (TypedFunction f) (Registry values functions specializations modifiers) =-  Registry values (addFunction f functions) specializations modifiers+addToRegistry t (Registry entries specializations modifiers) =+  Registry (addEntry t entries) specializations modifiers  -- | Concatenate a registry to another statefully (to be used with $(makeGenerators ''MyType)) concatUnsafeS :: (MonadState (Registry ins out) m) => Registry ins' out' -> m ()@@ -64,13 +62,11 @@  -- | Register modifications of the registry without changing its type addToRegistryUnsafe :: (Typeable a) => Typed a -> Registry ins out -> Registry ins out-addToRegistryUnsafe (TypedValue v) (Registry values functions specializations modifiers) =-  Registry (addValue v values) functions specializations modifiers-addToRegistryUnsafe (TypedFunction f) (Registry values functions specializations modifiers) =-  Registry values (addFunction f functions) specializations modifiers+addToRegistryUnsafe t (Registry entries specializations modifiers) =+  Registry (addEntry t entries) specializations modifiers  -- | Concatenate 2 registries concatRegistryUnsafe :: Registry ins out -> Registry ins' out' -> Registry ins' out' concatRegistryUnsafe-  (Registry vs1 fs1 ss1 ms1)-  (Registry vs2 fs2 ss2 ms2) = Registry (vs1 <> vs2) (fs1 <> fs2) (ss1 <> ss2) (ms1 <> ms2)+  (Registry fs1 ss1 ms1)+  (Registry fs2 ss2 ms2) = Registry (fs1 <> fs2) (ss1 <> ss2) (ms1 <> ms2)
src/Data/Registry/Statistics.hs view
@@ -30,8 +30,8 @@ --   of a given type makeStatisticsEither :: forall a ins out. (Typeable a) => Registry ins out -> Either Text Statistics makeStatisticsEither registry =-  let values = _values registry-      functions = _functions registry+  let values = mempty+      entries = _entries registry       specializations = _specializations registry       modifiers = _modifiers registry       targetType = someTypeRep (Proxy :: Proxy a)@@ -39,7 +39,7 @@       -- the list of values is kept as some State so that newly created values can be added to the current state       case evalStackWithValues         values-        (makeUntyped targetType (Context [(targetType, Nothing)]) functions specializations modifiers) of+        (makeUntyped targetType (Context [(targetType, Nothing)]) entries specializations modifiers) of         Left e ->           Left $             "could not create a " <> show targetType <> " out of the registry because " <> e <> "\nThe registry is\n"
test/Test/Data/Registry/Internal/GensRegistry.hs view
@@ -29,10 +29,10 @@     <: fun (genList @Specialization)     <: funTo @Gen Specialization     -- functions-    <: funTo @Gen Functions+    <: funTo @Gen Entries     <: fun (genList @Function)-    <: fun (genMultiMap @SomeTypeRep @Function)-    <: fun (genPair @SomeTypeRep @Function)+    <: fun (genMultiMap @SomeTypeRep @Untyped)+    <: fun (genPair @SomeTypeRep @Untyped)     <: funTo @Gen Function     <: funTo @Gen FunctionDescription     -- values@@ -72,8 +72,7 @@ genTextToInt = pure (TextToInt T.length)  data UntypedRegistry = UntypedRegistry-  { _uvalues :: Values,-    _ufunctions :: Functions,+  { _ufunctions :: Entries,     _uspecializations :: Specializations,     _umodifiers :: Modifiers   }
test/Test/Data/Registry/Internal/MakeSpec.hs view
@@ -16,7 +16,7 @@   function <- forall @Function   target <- forall @SomeTypeRep   context' <- forall @Context-  functions <- forall @Functions+  functions <- forall @Entries   specializations <- forall @Specializations   modifiers <- forall @Modifiers   values <- forall @Values
test/Test/Data/Registry/Internal/RegistrySpec.hs view
@@ -37,15 +37,15 @@ test_find_no_constructor = prop "no constructor can be found if nothing is stored in the registry" $ do   value <- forAll $ gen @Int -  (fromDynamic . funDyn <$> findFunction (valueDynTypeRep (createValue value)) mempty) === (Nothing :: Maybe (Maybe Int))+  (fromDynamic . untypedDyn <$> findUntyped (valueDynTypeRep (createValue value)) mempty) === (Nothing :: Maybe (Maybe Int))  test_find_contructor = prop "find a constructor in a list of constructors" $ do   (TextToInt function) <- forAll $ gen @TextToInt-  functions <- forAll $ (createFunction function `addFunction`) <$> gen @Functions+  functions <- forAll $ addEntry (TypedFunction $ createFunction function)  <$> gen @Entries    let outputType = dynTypeRep (toDyn (1 :: Int)) -  (fmap TextToInt <$> (fromDynamic . funDyn <$> findFunction outputType functions))+  (fmap TextToInt <$> (fromDynamic . untypedDyn <$> findUntyped outputType functions))     === Just (Just (TextToInt function))  test_store_value_no_modifiers = prop "a value can be stored in the list of values" $ do
test/Test/Data/Registry/Make/SpecializationFunctionsSpec.hs view
@@ -56,6 +56,28 @@   annotate "if inputs are missing for a specialization, we use the default value"   c2 === Config 3 +test_override_bug = test "we can override an IO value with an IO function" $ do+  let r = funTo @IO (Config 2)+            <: valTo @IO (Config 1)++  c1 <- liftIO $ make @(IO Config) r++  c1 === Config 2++test_override_specialized_bug = test "we can specialize an IO value with an IO function" $ do+  let r = specialize @(IO UseConfig2) (funTo @IO $ \(n::Int) -> Config n) $+         funTo @IO UseConfig2+        <: funTo @IO UseConfig1+        <: funTo @IO (Config 2)+            <: valTo @IO (Config 1)+            <: valTo @IO (5 :: Int)++  uc1 <- liftIO $ make @(IO UseConfig1) r+  uc2 <- liftIO $ make @(IO UseConfig2) r+  printConfig1 uc1 === Config 2+  printConfig2 uc2 === Config 5++ -- we want the following graph {-             +----------  Base  ------------+