@@ -1,8 +1,8 @@
11-- @inline export makeLayer arity=1
22-- @inline export runLayer arity=2
33module Yoga.Om.Layer
4− ( OmLayer(..)
5− , Finalizers(..)
4+ ( OmLayer
5+ , Finalizers
66 , makeLayer
77 , makeScopedLayer
88 , bracketLayer
@@ -20,8 +20,6 @@ module Yoga.Om.Layer
2020import Prelude
2121
2222import Data.Array as Array
23−import Data.Newtype (class Newtype)
24−import Data.Tuple.Nested ((/\), type (/\))
2523import Data.Foldable (for_)
2624import Effect.Aff (Aff, generalBracket)
2725import Effect.Aff.Class (liftAff)
@@ -43,8 +41,6 @@ import Yoga.Om as Om
4341-- | executed in reverse (LIFO) by `runScoped`.
4442newtype Finalizers = Finalizers (Array (Aff Unit))
4543
46−derive instance Newtype Finalizers _
47−
4844instance Semigroup Finalizers where
4945 append (Finalizers a) (Finalizers b) = Finalizers (a <> b)
5046
@@ -56,11 +52,11 @@ instance Monoid Finalizers where
5652-- carries finalizers for resource cleanup
5753-- =============================================================================
5854
55+type Built prov = { provisions :: Record prov, finalizers :: Finalizers }
56+
5957-- | A layer that requires dependencies (req), provides services (prov),
6058-- | and may carry finalizers for scoped resource management.
61−newtype OmLayer req prov err = OmLayer (Om (Record req) err (Record prov /\ Finalizers))
62−
63−derive instance Newtype (OmLayer req prov err) _
59+data OmLayer req prov err = OmLayer (Om (Record req) err (Built prov))
6460
6561-- =============================================================================
6662-- Layer constructors
@@ -68,7 +64,7 @@ derive instance Newtype (OmLayer req prov err) _
6864
6965-- | Create a layer from an Om computation (no finalizers).
7066makeLayer :: 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 })
7268
7369-- | Create a scoped layer with acquire/release semantics.
7470-- | The release function is guaranteed to run when `runScoped` closes the scope.
@@ -78,10 +74,9 @@ makeScopedLayer
7874 -> (Record prov -> Aff Unit)
7975 -> OmLayer req prov err
8076makeScopedLayer acquire release = OmLayer do
81− prov <- acquire
82− pure (prov /\ finalizer prov)
83− where
84− finalizer prov = Finalizers [ release prov ]
77+ provisions <- acquire
78+ let finalizers = Finalizers [ release provisions ]
79+ pure { provisions, finalizers }
8580
8681-- | Bracket-style scoped layer: acquire a resource, build provisions from it,
8782-- | and register a finalizer for the resource.
@@ -93,10 +88,9 @@ bracketLayer
9388 -> OmLayer req prov err
9489bracketLayer acquire release use = OmLayer do
9590 resource <- acquire
96− prov <- use resource
97− pure (prov /\ finalizer resource)
98− where
99− finalizer resource = Finalizers [ release resource ]
91+ provisions <- use resource
92+ let finalizers = Finalizers [ release resource ]
93+ pure { provisions, finalizers }
10094
10195-- =============================================================================
10296-- Custom Type Errors for Missing Dependencies
@@ -180,10 +174,10 @@ runLayer
180174 => Record available
181175 -> OmLayer req prov err
182176 -> Om (Record available) err (Record prov)
183−runLayer _ctx layer = unsafeCastLayer layer <#> \(prov /\ _) -> prov
177+runLayer _ctx (OmLayer om) = widenCtx om <#> _.provisions
184178 where
185− unsafeCastLayer :: OmLayer req prov err -> Om (Record available) err (Record prov /\ Finalizers)
186− unsafeCastLayer = unsafeCoerce
179+ widenCtx :: Om (Record req) err (Built prov) -> Om (Record available) err (Built prov)
180+ widenCtx = unsafeCoerce
187181
188182-- | Build a fully-provided layer, run finalizers, return the provisions.
189183-- | Useful when you just need the built services.
@@ -204,13 +198,13 @@ withScoped
204198withScoped (OmLayer om) callback = generalBracket acquire conditions use
205199 where
206200 acquire = Om.runOm {} errorHandlers om
207− errorHandlers = { exception: \_ -> pure (unsafeCoerce {} /\ mempty) }
201+ errorHandlers = { exception: \_ -> pure { provisions: unsafeCoerce {}, finalizers: mempty } }
208202 conditions =
209− { completed: \_ (_ /\ fins) -> runFinalizers fins
210− , failed: \_ (_ /\ fins) -> runFinalizers fins
211− , killed: \_ (_ /\ fins) -> runFinalizers fins
203+ { completed: \_ built -> runFinalizers built.finalizers
204+ , failed: \_ built -> runFinalizers built.finalizers
205+ , killed: \_ built -> runFinalizers built.finalizers
212206 }
213− use (prov /\ _) = callback prov
207+ use built = callback built.provisions
214208
215209-- | Run finalizers in reverse order (LIFO).
216210runFinalizers :: Finalizers -> Aff Unit
@@ -236,9 +230,11 @@ combineRequirements
236230 -> OmLayer req2 prov2 err2
237231 -> OmLayer reqDeduped provMerged ()
238232combineRequirements (OmLayer build1) (OmLayer build2) = OmLayer do
239− prov1 /\ fins1 <- Om.expand build1
240− prov2 /\ fins2 <- Om.expand build2
241− pure (Record.merge prov1 prov2 /\ (fins1 <> fins2))
233+ built1 <- Om.expand build1
234+ built2 <- Om.expand build2
235+ let provisions = Record.merge built1.provisions built2.provisions
236+ let finalizers = built1.finalizers <> built2.finalizers
237+ pure { provisions, finalizers }
242238
243239-- =============================================================================
244240-- Vertical composition — feed output of one layer into input of another
@@ -256,11 +252,12 @@ provide
256252 -> OmLayer req prov1 err1
257253 -> OmLayer req prov2 ()
258254provide (OmLayer layer2) (OmLayer layer1) = OmLayer do
259− prov1 /\ fins1 <- Om.expand layer1
260− prov2 /\ fins2 <- runLayer2 prov1
261− pure (prov2 /\ (fins1 <> fins2))
255+ built1 <- Om.expand layer1
256+ built2 <- runLayer2 built1.provisions
257+ let finalizers = built1.finalizers <> built2.finalizers
258+ pure { provisions: built2.provisions, finalizers }
262259 where
263260 runLayer2 ctx = liftAff $ Om.runOm ctx errorHandlers (Om.expand layer2)
264− errorHandlers = { exception: \_ -> pure (unsafeCoerce {} /\ mempty) }
261+ errorHandlers = { exception: \_ -> pure { provisions: unsafeCoerce {}, finalizers: mempty } }
265262
266263infixl 9 provide as >->