@@ -1,8 +1,8 @@
1-- @inline export makeLayer arity=1
1-- @inline export makeLayer arity=1
2-- @inline export runLayer arity=2
2-- @inline export runLayer arity=2
3module Yoga.Om.Layer
3module Yoga.Om.Layer
4− ( OmLayer(..)
4+ ( OmLayer
5− , Finalizers(..)
5+ , Finalizers
6 , makeLayer
6 , makeLayer
7 , makeScopedLayer
7 , makeScopedLayer
8 , bracketLayer
8 , bracketLayer
@@ -20,8 +20,6 @@ module Yoga.Om.Layer
20import Prelude
20import Prelude
22import Data.Array as Array
22import Data.Array as Array
23−import Data.Newtype (class Newtype)
24−import Data.Tuple.Nested ((/\), type (/\))
25import Data.Foldable (for_)
23import Data.Foldable (for_)
26import Effect.Aff (Aff, generalBracket)
24import Effect.Aff (Aff, generalBracket)
27import Effect.Aff.Class (liftAff)
25import Effect.Aff.Class (liftAff)
@@ -43,8 +41,6 @@ import Yoga.Om as Om
43-- | executed in reverse (LIFO) by `runScoped`.
41-- | executed in reverse (LIFO) by `runScoped`.
44newtype Finalizers = Finalizers (Array (Aff Unit))
42newtype Finalizers = Finalizers (Array (Aff Unit))
46−derive instance Newtype Finalizers _
48instance Semigroup Finalizers where
44instance Semigroup Finalizers where
49 append (Finalizers a) (Finalizers b) = Finalizers (a <> b)
45 append (Finalizers a) (Finalizers b) = Finalizers (a <> b)
@@ -56,11 +52,11 @@ instance Monoid Finalizers where
56-- carries finalizers for resource cleanup
52-- carries finalizers for resource cleanup
57-- =============================================================================
53-- =============================================================================
55+type Built prov = { provisions :: Record prov, finalizers :: Finalizers }
59-- | A layer that requires dependencies (req), provides services (prov),
57-- | A layer that requires dependencies (req), provides services (prov),
60-- | and may carry finalizers for scoped resource management.
58-- | and may carry finalizers for scoped resource management.
61−newtype OmLayer req prov err = OmLayer (Om (Record req) err (Record prov /\ Finalizers))
59+data OmLayer req prov err = OmLayer (Om (Record req) err (Built prov))
63−derive instance Newtype (OmLayer req prov err) _
65-- =============================================================================
61-- =============================================================================
66-- Layer constructors
62-- Layer constructors
@@ -68,7 +64,7 @@ derive instance Newtype (OmLayer req prov err) _
69-- | Create a layer from an Om computation (no finalizers).
65-- | Create a layer from an Om computation (no finalizers).
70makeLayer :: forall req prov err. Om (Record req) err (Record prov) -> OmLayer req prov err
66makeLayer :: forall req prov err. Om (Record req) err (Record prov) -> OmLayer req prov err
71−makeLayer om = OmLayer (om <#> \r -> r /\ mempty)
67+makeLayer om = OmLayer (om <#> \provisions -> { provisions, finalizers: mempty })
73-- | Create a scoped layer with acquire/release semantics.
69-- | Create a scoped layer with acquire/release semantics.
74-- | The release function is guaranteed to run when `runScoped` closes the scope.
70-- | The release function is guaranteed to run when `runScoped` closes the scope.
@@ -78,10 +74,9 @@ makeScopedLayer
78 -> (Record prov -> Aff Unit)
74 -> (Record prov -> Aff Unit)
79 -> OmLayer req prov err
75 -> OmLayer req prov err
80makeScopedLayer acquire release = OmLayer do
76makeScopedLayer acquire release = OmLayer do
81− prov <- acquire
77+ provisions <- acquire
82− pure (prov /\ finalizer prov)
84− finalizer prov = Finalizers [ release prov ]
78+ let finalizers = Finalizers [ release provisions ]
79+ pure { provisions, finalizers }
86-- | Bracket-style scoped layer: acquire a resource, build provisions from it,
81-- | Bracket-style scoped layer: acquire a resource, build provisions from it,
87-- | and register a finalizer for the resource.
82-- | and register a finalizer for the resource.
@@ -93,10 +88,9 @@ bracketLayer
93 -> OmLayer req prov err
88 -> OmLayer req prov err
94bracketLayer acquire release use = OmLayer do
89bracketLayer acquire release use = OmLayer do
95 resource <- acquire
90 resource <- acquire
96− prov <- use resource
91+ provisions <- use resource
97− pure (prov /\ finalizer resource)
99− finalizer resource = Finalizers [ release resource ]
92+ let finalizers = Finalizers [ release resource ]
93+ pure { provisions, finalizers }
101-- =============================================================================
95-- =============================================================================
102-- Custom Type Errors for Missing Dependencies
96-- Custom Type Errors for Missing Dependencies
@@ -180,10 +174,10 @@ runLayer
180 => Record available
174 => Record available
181 -> OmLayer req prov err
175 -> OmLayer req prov err
182 -> Om (Record available) err (Record prov)
176 -> Om (Record available) err (Record prov)
183−runLayer _ctx layer = unsafeCastLayer layer <#> \(prov /\ _) -> prov
177+runLayer _ctx (OmLayer om) = widenCtx om <#> _.provisions
185− unsafeCastLayer :: OmLayer req prov err -> Om (Record available) err (Record prov /\ Finalizers)
179+ widenCtx :: Om (Record req) err (Built prov) -> Om (Record available) err (Built prov)
186− unsafeCastLayer = unsafeCoerce
180+ widenCtx = unsafeCoerce
188-- | Build a fully-provided layer, run finalizers, return the provisions.
182-- | Build a fully-provided layer, run finalizers, return the provisions.
189-- | Useful when you just need the built services.
183-- | Useful when you just need the built services.
@@ -204,13 +198,13 @@ withScoped
204withScoped (OmLayer om) callback = generalBracket acquire conditions use
198withScoped (OmLayer om) callback = generalBracket acquire conditions use
206 acquire = Om.runOm {} errorHandlers om
200 acquire = Om.runOm {} errorHandlers om
207− errorHandlers = { exception: \_ -> pure (unsafeCoerce {} /\ mempty) }
201+ errorHandlers = { exception: \_ -> pure { provisions: unsafeCoerce {}, finalizers: mempty } }
208 conditions =
202 conditions =
209− { completed: \_ (_ /\ fins) -> runFinalizers fins
203+ { completed: \_ built -> runFinalizers built.finalizers
210− , failed: \_ (_ /\ fins) -> runFinalizers fins
204+ , failed: \_ built -> runFinalizers built.finalizers
211− , killed: \_ (_ /\ fins) -> runFinalizers fins
205+ , killed: \_ built -> runFinalizers built.finalizers
213− use (prov /\ _) = callback prov
207+ use built = callback built.provisions
215-- | Run finalizers in reverse order (LIFO).
209-- | Run finalizers in reverse order (LIFO).
216runFinalizers :: Finalizers -> Aff Unit
210runFinalizers :: Finalizers -> Aff Unit
@@ -236,9 +230,11 @@ combineRequirements
236 -> OmLayer req2 prov2 err2
230 -> OmLayer req2 prov2 err2
237 -> OmLayer reqDeduped provMerged ()
231 -> OmLayer reqDeduped provMerged ()
238combineRequirements (OmLayer build1) (OmLayer build2) = OmLayer do
232combineRequirements (OmLayer build1) (OmLayer build2) = OmLayer do
239− prov1 /\ fins1 <- Om.expand build1
233+ built1 <- Om.expand build1
240− prov2 /\ fins2 <- Om.expand build2
234+ built2 <- Om.expand build2
241− pure (Record.merge prov1 prov2 /\ (fins1 <> fins2))
235+ let provisions = Record.merge built1.provisions built2.provisions
236+ let finalizers = built1.finalizers <> built2.finalizers
237+ pure { provisions, finalizers }
243-- =============================================================================
239-- =============================================================================
244-- Vertical composition — feed output of one layer into input of another
240-- Vertical composition — feed output of one layer into input of another
@@ -256,11 +252,12 @@ provide
256 -> OmLayer req prov1 err1
252 -> OmLayer req prov1 err1
257 -> OmLayer req prov2 ()
253 -> OmLayer req prov2 ()
258provide (OmLayer layer2) (OmLayer layer1) = OmLayer do
254provide (OmLayer layer2) (OmLayer layer1) = OmLayer do
259− prov1 /\ fins1 <- Om.expand layer1
255+ built1 <- Om.expand layer1
260− prov2 /\ fins2 <- runLayer2 prov1
256+ built2 <- runLayer2 built1.provisions
261− pure (prov2 /\ (fins1 <> fins2))
257+ let finalizers = built1.finalizers <> built2.finalizers
258+ pure { provisions: built2.provisions, finalizers }
263 runLayer2 ctx = liftAff $ Om.runOm ctx errorHandlers (Om.expand layer2)
260 runLayer2 ctx = liftAff $ Om.runOm ctx errorHandlers (Om.expand layer2)
264− errorHandlers = { exception: \_ -> pure (unsafeCoerce {} /\ mempty) }
261+ errorHandlers = { exception: \_ -> pure { provisions: unsafeCoerce {}, finalizers: mempty } }
266infixl 9 provide as >->
263infixl 9 provide as >->