-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Toy dependency injection framework -- -- Toy dependency injection framework that wires things at runtime. @package cauldron @version 0.4.0.0 -- | This is a library for performing dependency injection. It's an -- alternative to manually wiring your functions and passing all required -- parameters explicitly. Instead of that, you throw your functions into -- a Cauldron, which wires them for you, guiding itself by the -- types. -- -- Wiring errors are detected at runtime, not at compile time. -- -- This library should be used at the "composition root" of the -- application, and only there: the components we are wiring together -- need not be aware that the library exists. -- --
-- >>> :{
-- data A = A deriving Show
-- data B = B deriving Show
-- data C = C deriving Show
-- makeA :: A
-- makeA = A
-- makeB :: A -> B
-- makeB = \_ -> B
-- makeC :: A -> B -> IO C
-- makeC = \_ _ -> pure C
-- :}
--
--
--
-- >>> :{
-- do
-- let cauldron :: Cauldron IO
-- cauldron =
-- emptyCauldron
-- & insert @A do makeBean do pack value makeA
-- & insert @B do makeBean do pack value makeB
-- & insert @C do makeBean do pack effect makeC
-- Right (_ :: DependencyGraph, action) = cook forbidDepCycles cauldron
-- beans <- action
-- pure do taste @C beans
-- :}
-- Just C
--
module Cauldron
-- | A map of Bean recipes. Parameterized by the monad m in
-- which the Bean Constructors might have effects.
data Cauldron (m :: Type -> Type)
emptyCauldron :: forall (m :: Type -> Type). Cauldron m
-- | Put a recipe for a Bean into the Cauldron.
--
-- Only one recipe is allowed for each different bean type, so
-- insert for a bean will overwrite previous recipes for
-- that type.
insert :: forall bean (m :: Type -> Type). Typeable bean => Bean m bean -> Cauldron m -> Cauldron m
-- | Tweak an already existing Bean recipe.
adjust :: forall bean (m :: Type -> Type). Typeable bean => (Bean m bean -> Bean m bean) -> Cauldron m -> Cauldron m
delete :: forall {k} (bean :: k) (m :: Type -> Type). Typeable bean => Cauldron m -> Cauldron m
-- | Change the monad used by the beans in the Cauldron.
hoistCauldron :: (forall x. () => m x -> n x) -> Cauldron m -> Cauldron n
-- | A bean recipe, to be inserted into a Cauldron.
data Bean (m :: Type -> Type) bean
[Bean] :: forall (m :: Type -> Type) bean. Constructor m bean -> Decos m bean -> Bean m bean
-- | A Bean without decorators, having only the main constructor.
makeBean :: forall (m :: Type -> Type) a. Constructor m a -> Bean m a
setConstructor :: forall (m :: Type -> Type) bean. Constructor m bean -> Bean m bean -> Bean m bean
setDecos :: forall (m :: Type -> Type) bean. Decos m bean -> Bean m bean -> Bean m bean
overDecos :: forall (m :: Type -> Type) bean. (Decos m bean -> Decos m bean) -> Bean m bean -> Bean m bean
-- | Change the monad used by the bean's Constructor and its
-- Decos.
hoistBean :: (forall x. () => m x -> n x) -> Bean m bean -> Bean n bean
-- | A list of Constructors for the decorators of some Bean.
--
-- Constructors for a decorator will have the bean itself
-- among their arguments. That bean argument will be either the
-- "bare" undecorated bean (for the first decorator) or the result of
-- applying the previous decorator in the list.
--
-- Decorators can have other dependencies besides the bean.
data Decos (m :: Type -> Type) bean
-- | Empty list of decorators.
emptyDecos :: forall (m :: Type -> Type) bean. Decos m bean
-- | Build the decorators from a list of Constructors, first
-- innermost, last outermost.
fromConstructors :: forall (m :: Type -> Type) bean. [Constructor m bean] -> Decos m bean
-- | Add a new decorator that modifies the bean after all existing
-- decorators.
--
-- This means the behaviours it adds to the bean's methods will be
-- applied first when entering the method.
addOuter :: forall (m :: Type -> Type) bean. Constructor m bean -> Decos m bean -> Decos m bean
-- | Add a new decorator that modifies the bean before all existing
-- decorators.
--
-- This means the behaviours it adds to the bean's methods will be
-- applied last, just before entering the base bean's method.
--
-- Usually addOuter is preferrable.
addInner :: forall (m :: Type -> Type) bean. Constructor m bean -> Decos m bean -> Decos m bean
-- | Change the monad used by the decorators.
hoistDecos :: (forall x. () => m x -> n x) -> Decos m bean -> Decos n bean
-- | A way of building some bean value, potentially requiring some
-- dependencies, potentially returning some secondary beans along the
-- primary bean result, and also potentially requiring some
-- initialization effect in a monad m.
--
-- Note that only the type of the primary bean is reflected in
-- the Constructor type. Those of the dependencies and secondary
-- beans are not.
--
-- A typical initialization monad will be IO, used for example to
-- create mutable references that the bean will use internally. Sometimes
-- the a constructor will allocate resources with bracket-like
-- operations, and in that case a monad like Managed might be
-- needed instead.
data Constructor (m :: Type -> Type) bean
-- | Take a curried function that constructs a bean, uncurry it recursively
-- and then apply a Packer to its tip, resulting in a
-- Constructor.
--
--
-- >>> :{
-- data A = A deriving Show
-- data B = B deriving Show
-- data C = C deriving Show
-- makeB :: A -> B
-- makeB = \_ -> B
-- makeC :: A -> B -> IO C
-- makeC = \_ _ -> pure C
-- constructorB :: Constructor IO B
-- constructorB = pack value makeB
-- constructorC :: Constructor IO C
-- constructorC = pack effect makeC
-- :}
--
--
-- There are pack0, pack1... functions which work for
-- specific number of arguments, but the generic pack should work
-- in most cases anyway.
pack :: forall (args :: [Type]) r curried (regs :: [Type]) bean (m :: Type -> Type). (MulticurryableF args r curried (IsFunction curried), All (Typeable :: Type -> Constraint) args, All (And (Typeable :: Type -> Constraint) Monoid) regs) => Packer m regs bean r -> curried -> Constructor m bean
-- | Slightly simpler version of pack for 0-argument
-- functions.
pack0 :: forall (regs :: [Type]) (m :: Type -> Type) bean r. All (And (Typeable :: Type -> Constraint) Monoid) regs => Packer m regs bean r -> r -> Constructor m bean
-- | Slightly simpler version of pack for 1-argument
-- functions.
pack1 :: forall arg1 r (m :: Type -> Type) (regs :: [Type]) bean. (Typeable arg1, All (And (Typeable :: Type -> Constraint) Monoid) regs) => Packer m regs bean r -> (arg1 -> r) -> Constructor m bean
-- | Slightly simpler version of pack for 2-argument
-- functions.
pack2 :: forall arg1 arg2 r (m :: Type -> Type) (regs :: [Type]) bean. (Typeable arg1, Typeable arg2, All (And (Typeable :: Type -> Constraint) Monoid) regs) => Packer m regs bean r -> (arg1 -> arg2 -> r) -> Constructor m bean
-- | Slightly simpler version of pack for 3-argument
-- functions.
pack3 :: forall arg1 arg2 arg3 r (m :: Type -> Type) (regs :: [Type]) bean. (Typeable arg1, Typeable arg2, Typeable arg3, All (And (Typeable :: Type -> Constraint) Monoid) regs) => Packer m regs bean r -> (arg1 -> arg2 -> arg3 -> r) -> Constructor m bean
-- | Change the monad in which the Constructor's effects take place.
hoistConstructor :: (forall x. () => m x -> n x) -> Constructor m bean -> Constructor n bean
-- | Applies a transformation to the tip of a curried function, coaxing it
-- into the shape expected by a Constructor, which includes
-- information about which is the primary bean and which are the
-- secondary ones.
--
--
-- >>> :{
-- data A = A deriving Show
-- data B = B deriving Show
-- makeB :: A -> (Sum Int, B)
-- makeB = \_ -> (Sum 1, B)
-- constructorB :: Constructor IO B
-- constructorB = pack (valueWith \(s,bean) -> regs1 s bean) makeB
-- :}
--
valueWith :: forall (m :: Type -> Type) (regs :: [Type]) r bean. (Applicative m, All (And (Typeable :: Type -> Constraint) Monoid) regs) => (r -> Regs regs bean) -> Packer m regs bean r
-- |
-- >>> :{
-- data A = A deriving Show
-- data B = B deriving Show
-- makeB :: A -> IO (Sum Int, B)
-- makeB = \_ -> pure (Sum 1, B)
-- constructorB :: Constructor IO B
-- constructorB = pack (effectWith \(s,bean) -> regs1 s bean) makeB
-- :}
--
effectWith :: forall m (regs :: [Type]) r bean. (Applicative m, All (And (Typeable :: Type -> Constraint) Monoid) regs) => (r -> Regs regs bean) -> Packer m regs bean (m r)
-- | Auxiliary type which contains a primary bean along with zero or more
-- secondary beans. The secondary beans must have Monoid
-- instances.
data Regs (regs :: [Type]) bean
-- | A primary bean without secondary beans.
regs0 :: bean -> Regs ('[] :: [Type]) bean
-- | A primary bean with one secondary bean.
regs1 :: reg1 -> bean -> Regs '[reg1] bean
-- | A primary bean with two secondary beans.
regs2 :: reg1 -> reg2 -> bean -> Regs '[reg1, reg2] bean
-- | A primary bean with three secondary beans.
regs3 :: reg1 -> reg2 -> reg3 -> bean -> Regs '[reg1, reg2, reg3] bean
-- | Build the beans using the recipes stored in the Cauldron.
cook :: Monad m => Fire m -> Cauldron m -> Either BadBeans (DependencyGraph, m BoiledBeans)
-- | Cook a list of Cauldrons.
--
-- Cauldrons later in the list can see the beans in all previous
-- Cauldrons, but not vice versa.
--
-- Beans in a Cauldron have priority over the same beans in
-- previous Cauldrons.
cookNonEmpty :: Monad m => NonEmpty (Fire m, Cauldron m) -> Either BadBeans (NonEmpty DependencyGraph, m (NonEmpty BoiledBeans))
-- | Cook a hierarchy of Cauldrons.
--
-- Cauldrons down in the branches can see the beans of their
-- ancestor Cauldrons, but not vice versa.
--
-- Beans in a Cauldron have priority over the same beans in
-- ancestor Cauldrons.
cookTree :: Monad m => Tree (Fire m, Cauldron m) -> Either BadBeans (Tree DependencyGraph, m (Tree BoiledBeans))
-- | Strategy for dealing with dependency cycles.
--
-- (Terrible uninformative name caused by a metaphor stretched too far.)
data Fire (m :: Type -> Type)
-- | Forbid any kind of cyclic dependencies between beans. This is probably
-- what you want.
forbidDepCycles :: forall (m :: Type -> Type). Monad m => Fire m
-- | Allow direct self-dependencies.
--
-- A bean constructor might depend on itself. This can be useful for
-- having decorated self-invocations, because the version of the bean
-- received as argument comes "from the future" and is already decorated.
-- (BEWARE: Pattern-matching too eagerly on this "bean from the
-- future" during construction will cause infinite loops.)
--
-- Note that a MonadFix instance is required of the initialization
-- monad.
allowSelfDeps :: forall (m :: Type -> Type). MonadFix m => Fire m
-- | The successful result of cooking a Cauldron. Can't do a
-- lot with them other than to taste them.
data BoiledBeans
-- | Return the resulting bean, if present.
taste :: Typeable bean => BoiledBeans -> Maybe bean
-- | Sometimes the cooking process goes wrong.
data BadBeans
-- | The Cauldron identified by PathToCauldron has beans that
-- depend on beans that can't be found either in the current
-- Cauldron or its ancestors.
MissingDependencies :: PathToCauldron -> Map TypeRep (Set TypeRep) -> BadBeans
-- | Beans that work both as primary beans and as secondary beans are
-- disallowed.
DoubleDutyBeans :: Set TypeRep -> BadBeans
-- | Dependency cycles are disallowed by some Fires.
DependencyCycle :: NonEmpty BeanConstructionStep -> BadBeans
-- | Will always be [] when using cook; identifies a
-- Cauldron in a hierarchy of Cauldrons when using
-- cookNonEmpty or cookTree.
type PathToCauldron = [Int]
-- | An edge means that the source depends on the target.
--
-- The dependencies of each bean are given separatedly from its
-- decorators.
data DependencyGraph
-- | See the DOT format.
exportToDot :: (BeanConstructionStep -> Text) -> FilePath -> DependencyGraph -> IO ()
defaultStepToText :: BeanConstructionStep -> Text
-- | A step in the construction of a bean value.
data BeanConstructionStep
-- | Undecorated bean.
BarePrimaryBean :: TypeRep -> BeanConstructionStep
-- | Apply the decorator with the given index. Comes after the
-- BarePrimaryBean and all PrimaryBeanDecos with a lower
-- index value.
PrimaryBeanDeco :: TypeRep -> Int -> BeanConstructionStep
-- | Final, fully decorated version of a bean. If there are no decorators,
-- comes directly after BarePrimaryBean.
PrimaryBean :: TypeRep -> BeanConstructionStep
-- | Beans that are secondary registrations of a Constructor and
-- which are aggregated monoidally.
SecondaryBean :: TypeRep -> BeanConstructionStep
removeSecondaryBeans :: DependencyGraph -> DependencyGraph
removeDecos :: DependencyGraph -> DependencyGraph
-- | Unifies PrimaryBeans with their respective
-- BarePrimaryBeans and PrimaryBeanDecos.
--
-- Also removes any self-loops.
collapsePrimaryBeans :: DependencyGraph -> DependencyGraph
-- | Conversion to a graph type from the algebraic-graphs library
-- for further processing.
toAdjacencyMap :: DependencyGraph -> AdjacencyMap BeanConstructionStep
instance GHC.Internal.Base.Applicative (Cauldron.Args args)
instance GHC.Internal.Base.Applicative Cauldron.Extractor
instance Data.Functor.Contravariant.Contravariant (Cauldron.Packer m regs bean)
instance GHC.Classes.Eq Cauldron.BeanConstructionStep
instance GHC.Internal.Base.Functor (Cauldron.Args args)
instance GHC.Internal.Base.Functor Cauldron.Extractor
instance GHC.Internal.Base.Functor (Cauldron.Regs regs)
instance GHC.Internal.IsList.IsList (Cauldron.Decos m bean)
instance GHC.Internal.Base.Monad (Cauldron.Args args)
instance GHC.Internal.Base.Monoid (Cauldron.Cauldron m)
instance GHC.Internal.Base.Monoid (Cauldron.Decos m bean)
instance GHC.Classes.Ord Cauldron.BeanConstructionStep
instance GHC.Internal.Base.Semigroup (Cauldron.Cauldron m)
instance GHC.Internal.Base.Semigroup (Cauldron.Decos m bean)
instance GHC.Internal.Show.Show Cauldron.BadBeans
instance GHC.Internal.Show.Show Cauldron.BeanConstructionStep
module Cauldron.Managed
-- | This is a copy of the Managed type from the managed
-- package, with a dodgy MonadFix instance tacked on.
data Managed a
-- | Build a Managed value from a withFoo-style
-- resource-handling function that accepts a continuation, like
-- withFile.
--
-- Passing functions that do weird things like running their continuation
-- twice will tear apart the fabric of reality. Why would you want
-- to do that? Pass only withFoo-style functions.
managed :: (forall r. () => (a -> IO r) -> IO r) -> Managed a
-- | Make use of the managed resource by supplying a callback.
with :: Managed a -> (a -> IO b) -> IO b
instance GHC.Internal.Base.Applicative Cauldron.Managed.Managed
instance GHC.Internal.Base.Functor Cauldron.Managed.Managed
instance GHC.Internal.Control.Monad.Fix.MonadFix Cauldron.Managed.Managed
instance Control.Monad.IO.Class.MonadIO Cauldron.Managed.Managed
instance GHC.Internal.Base.Monad Cauldron.Managed.Managed