@@ -1,8 +1,8 @@
11{-# LANGUAGE UndecidableInstances #-}
2−-- | Lifted version of "Control.Concurrent.Async".
3−module Effectful.Concurrent.Async
4− ( Concurrent
5− , runConcurrent
2+module Effectful.Async
3+ ( -- * Async effect
4+ AsyncE
5+ , runAsyncE
66
77 -- * Asynchronous actions
88 , Async
@@ -76,37 +76,51 @@ import Control.Concurrent (threadDelay)
7676import Control.Concurrent.Async (Async)
7777import Control.Exception (Exception, SomeException)
7878import Control.Monad (forever)
79−import Data.Kind (Type)
8079import qualified Control.Concurrent.Async as A
8180import qualified UnliftIO.Async as U
8281import qualified UnliftIO.Internals.Async as I
8382
84−import Effectful.Concurrent.Effect
85−import Effectful.Dispatch.Static
86−import Effectful.Monad
83+import Effectful.Internal.Effect
84+import Effectful.Internal.Env
85+import Effectful.Internal.Monad
86+
87+-- | Run 'Eff' operations asynchronously via the @async@ library.
88+--
89+-- /Note:/ thread local state changes in 'Eff' operations run asynchronously
90+-- will not affect the parent thread.
91+--
92+-- /TODO:/ write about 'AsyncE' not respecting scoped operations.
93+data AsyncE :: Effect where
94+ AsyncE :: AsyncE m r
95+
96+runAsyncE :: IOE :> es => Eff (AsyncE : es) a -> Eff es a
97+runAsyncE = evalEffect (IdE AsyncE)
98+
99+----------------------------------------
100+-- Operations
87101
88102-- | Lifted 'A.async'.
89−async :: Concurrent :> es => Eff es a -> Eff es (Async a)
103+async :: AsyncE :> es => Eff es a -> Eff es (Async a)
90104async = liftAsync A.async
91105
92106-- | Lifted 'A.asyncBound'.
93−asyncBound :: Concurrent :> es => Eff es a -> Eff es (Async a)
107+asyncBound :: AsyncE :> es => Eff es a -> Eff es (Async a)
94108asyncBound = liftAsync A.asyncBound
95109
96110-- | Lifted 'A.asyncOn'.
97−asyncOn :: Concurrent :> es => Int -> Eff es a -> Eff es (Async a)
111+asyncOn :: AsyncE :> es => Int -> Eff es a -> Eff es (Async a)
98112asyncOn cpu = liftAsync (A.asyncOn cpu)
99113
100114-- | Lifted 'A.asyncWithUnmask'.
101115asyncWithUnmask
102− :: Concurrent :> es
116+ :: AsyncE :> es
103117 => ((forall b. Eff es b -> Eff es b) -> Eff es a)
104118 -> Eff es (Async a)
105119asyncWithUnmask = liftAsyncWithUnmask A.asyncWithUnmask
106120
107121-- | Lifted 'A.asyncOnWithUnmask'.
108122asyncOnWithUnmask
109− :: Concurrent :> es
123+ :: AsyncE :> es
110124 => Int
111125 -> ((forall b. Eff es b -> Eff es b) -> Eff es a)
112126 -> Eff es (Async a)
@@ -114,7 +128,7 @@ asyncOnWithUnmask cpu = liftAsyncWithUnmask (A.asyncOnWithUnmask cpu)
114128
115129-- | Lifted 'A.withAsync'.
116130withAsync
117− :: Concurrent :> es
131+ :: AsyncE :> es
118132 => Eff es a
119133 -> (Async a -> Eff es b)
120134 -> Eff es b
@@ -122,7 +136,7 @@ withAsync = liftWithAsync A.withAsync
122136
123137-- | Lifted 'A.withAsyncBound'.
124138withAsyncBound
125− :: Concurrent :> es
139+ :: AsyncE :> es
126140 => Eff es a
127141 -> (Async a -> Eff es b)
128142 -> Eff es b
@@ -130,7 +144,7 @@ withAsyncBound = liftWithAsync A.withAsyncBound
130144
131145-- | Lifted 'A.withAsyncOn'.
132146withAsyncOn
133− :: Concurrent :> es
147+ :: AsyncE :> es
134148 => Int
135149 -> Eff es a
136150 -> (Async a -> Eff es b)
@@ -139,7 +153,7 @@ withAsyncOn cpu = liftWithAsync (A.withAsyncOn cpu)
139153
140154-- | Lifted 'A.withAsyncWithUnmask'.
141155withAsyncWithUnmask
142− :: Concurrent :> es
156+ :: AsyncE :> es
143157 => ((forall c. Eff es c -> Eff es c) -> Eff es a)
144158 -> (Async a -> Eff es b)
145159 -> Eff es b
@@ -147,7 +161,7 @@ withAsyncWithUnmask = liftWithAsyncWithUnmask A.withAsyncWithUnmask
147161
148162-- | Lifted 'A.withAsyncOnWithUnmask'.
149163withAsyncOnWithUnmask
150− :: Concurrent :> es
164+ :: AsyncE :> es
151165 => Int
152166 -> ((forall c. Eff es c -> Eff es c) -> Eff es a)
153167 -> (Async a -> Eff es b)
@@ -155,60 +169,60 @@ withAsyncOnWithUnmask
155169withAsyncOnWithUnmask cpu = liftWithAsyncWithUnmask (A.withAsyncOnWithUnmask cpu)
156170
157171-- | Lifted 'A.wait'.
158−wait :: Concurrent :> es => Async a -> Eff es a
172+wait :: AsyncE :> es => Async a -> Eff es a
159173wait = unsafeEff_ . A.wait
160174
161175-- | Lifted 'A.poll'.
162176poll
163− :: Concurrent :> es
177+ :: AsyncE :> es
164178 => Async a
165179 -> Eff es (Maybe (Either SomeException a))
166180poll = unsafeEff_ . A.poll
167181
168182-- | Lifted 'A.cancel'.
169−cancel :: Concurrent :> es => Async a -> Eff es ()
183+cancel :: AsyncE :> es => Async a -> Eff es ()
170184cancel = unsafeEff_ . A.cancel
171185
172186-- | Lifted 'A.cancelWith'.
173−cancelWith :: (Exception e, Concurrent :> es) => Async a -> e -> Eff es ()
187+cancelWith :: (Exception e, AsyncE :> es) => Async a -> e -> Eff es ()
174188cancelWith a = unsafeEff_ . A.cancelWith a
175189
176190-- | Lifted 'A.uninterruptibleCancel'.
177−uninterruptibleCancel :: Concurrent :> es => Async a -> Eff es ()
191+uninterruptibleCancel :: AsyncE :> es => Async a -> Eff es ()
178192uninterruptibleCancel = unsafeEff_ . A.uninterruptibleCancel
179193
180194-- | Lifted 'A.waitCatch'.
181195waitCatch
182− :: Concurrent :> es
196+ :: AsyncE :> es
183197 => Async a
184198 -> Eff es (Either SomeException a)
185199waitCatch = unsafeEff_ . A.waitCatch
186200
187201-- | Lifted 'A.waitAny'.
188−waitAny :: Concurrent :> es => [Async a] -> Eff es (Async a, a)
202+waitAny :: AsyncE :> es => [Async a] -> Eff es (Async a, a)
189203waitAny = unsafeEff_ . A.waitAny
190204
191205-- | Lifted 'A.waitAnyCatch'.
192206waitAnyCatch
193− :: Concurrent :> es
207+ :: AsyncE :> es
194208 => [Async a]
195209 -> Eff es (Async a, Either SomeException a)
196210waitAnyCatch = unsafeEff_ . A.waitAnyCatch
197211
198212-- | Lifted 'A.waitAnyCancel'.
199−waitAnyCancel :: Concurrent :> es => [Async a] -> Eff es (Async a, a)
213+waitAnyCancel :: AsyncE :> es => [Async a] -> Eff es (Async a, a)
200214waitAnyCancel = unsafeEff_ . A.waitAnyCancel
201215
202216-- | Lifted 'A.waitAnyCatchCancel'.
203217waitAnyCatchCancel
204− :: Concurrent :> es
218+ :: AsyncE :> es
205219 => [Async a]
206220 -> Eff es (Async a, Either SomeException a)
207221waitAnyCatchCancel = unsafeEff_ . A.waitAnyCatchCancel
208222
209223-- | Lifted 'A.waitEither'.
210224waitEither
211− :: Concurrent :> es
225+ :: AsyncE :> es
212226 => Async a
213227 -> Async b
214228 -> Eff es (Either a b)
@@ -216,7 +230,7 @@ waitEither a b = unsafeEff_ $ A.waitEither a b
216230
217231-- | Lifted 'A.waitEitherCatch'.
218232waitEitherCatch
219− :: Concurrent :> es
233+ :: AsyncE :> es
220234 => Async a
221235 -> Async b
222236 -> Eff es (Either (Either SomeException a) (Either SomeException b))
@@ -224,7 +238,7 @@ waitEitherCatch a b = unsafeEff_ $ A.waitEitherCatch a b
224238
225239-- | Lifted 'A.waitEitherCancel'.
226240waitEitherCancel
227− :: Concurrent :> es
241+ :: AsyncE :> es
228242 => Async a
229243 -> Async b
230244 -> Eff es (Either a b)
@@ -232,53 +246,53 @@ waitEitherCancel a b = unsafeEff_ $ A.waitEitherCancel a b
232246
233247-- | Lifted 'A.waitEitherCatchCancel'.
234248waitEitherCatchCancel
235− :: Concurrent :> es
249+ :: AsyncE :> es
236250 => Async a
237251 -> Async b
238252 -> Eff es (Either (Either SomeException a) (Either SomeException b))
239253waitEitherCatchCancel a b = unsafeEff_ $ A.waitEitherCatch a b
240254
241255-- | Lifted 'A.waitEither_'.
242−waitEither_ :: Concurrent :> es => Async a -> Async b -> Eff es ()
256+waitEither_ :: AsyncE :> es => Async a -> Async b -> Eff es ()
243257waitEither_ a b = unsafeEff_ $ A.waitEither_ a b
244258
245259-- | Lifted 'A.waitBoth'.
246−waitBoth :: Concurrent :> es => Async a -> Async b -> Eff es (a, b)
260+waitBoth :: AsyncE :> es => Async a -> Async b -> Eff es (a, b)
247261waitBoth a b = unsafeEff_ $ A.waitBoth a b
248262
249263-- | Lifted 'A.link'.
250−link :: Concurrent :> es => Async a -> Eff es ()
264+link :: AsyncE :> es => Async a -> Eff es ()
251265link = unsafeEff_ . A.link
252266
253267-- | Lifted 'A.linkOnly'.
254−linkOnly :: Concurrent :> es => (SomeException -> Bool) -> Async a -> Eff es ()
268+linkOnly :: AsyncE :> es => (SomeException -> Bool) -> Async a -> Eff es ()
255269linkOnly f = unsafeEff_ . A.linkOnly f
256270
257271-- | Lifted 'A.link2'.
258−link2 :: Concurrent :> es => Async a -> Async b -> Eff es ()
272+link2 :: AsyncE :> es => Async a -> Async b -> Eff es ()
259273link2 a b = unsafeEff_ $ A.link2 a b
260274
261275-- | Lifted 'A.link2Only'.
262−link2Only :: Concurrent :> es => (SomeException -> Bool) -> Async a -> Async b -> Eff es ()
276+link2Only :: AsyncE :> es => (SomeException -> Bool) -> Async a -> Async b -> Eff es ()
263277link2Only f a b = unsafeEff_ $ A.link2Only f a b
264278
265279-- | Lifted 'A.race'.
266−race :: Concurrent :> es => Eff es a -> Eff es b -> Eff es (Either a b)
280+race :: AsyncE :> es => Eff es a -> Eff es b -> Eff es (Either a b)
267281race ma mb = unsafeEff $ \es -> do
268282 A.race (unEff ma =<< cloneEnv es) (unEff mb =<< cloneEnv es)
269283
270284-- | Lifted 'A.race_'.
271−race_ :: Concurrent :> es => Eff es a -> Eff es b -> Eff es ()
285+race_ :: AsyncE :> es => Eff es a -> Eff es b -> Eff es ()
272286race_ ma mb = unsafeEff $ \es -> do
273287 A.race_ (unEff ma =<< cloneEnv es) (unEff mb =<< cloneEnv es)
274288
275289-- | Lifted 'A.concurrently'.
276−concurrently :: Concurrent :> es => Eff es a -> Eff es b -> Eff es (a, b)
290+concurrently :: AsyncE :> es => Eff es a -> Eff es b -> Eff es (a, b)
277291concurrently ma mb = unsafeEff $ \es -> do
278292 A.concurrently (unEff ma =<< cloneEnv es) (unEff mb =<< cloneEnv es)
279293
280294-- | Lifted 'A.concurrently_'.
281−concurrently_ :: Concurrent :> es => Eff es a -> Eff es b -> Eff es ()
295+concurrently_ :: AsyncE :> es => Eff es a -> Eff es b -> Eff es ()
282296concurrently_ ma mb = unsafeEff $ \es -> do
283297 A.concurrently_ (unEff ma =<< cloneEnv es) (unEff mb =<< cloneEnv es)
284298
@@ -288,7 +302,7 @@ concurrently_ ma mb = unsafeEff $ \es -> do
288302
289303-- | Lifted 'A.mapConcurrently'.
290304mapConcurrently
291− :: (Traversable f, Concurrent :> es)
305+ :: (Traversable f, AsyncE :> es)
292306 => (a -> Eff es b)
293307 -> f a
294308 -> Eff es (f b)
@@ -297,7 +311,7 @@ mapConcurrently f t = unsafeEff $ \es -> do
297311
298312-- | Lifted 'A.mapConcurrently_'.
299313mapConcurrently_
300− :: (Foldable f, Concurrent :> es)
314+ :: (Foldable f, AsyncE :> es)
301315 => (a -> Eff es b)
302316 -> f a
303317 -> Eff es ()
@@ -306,7 +320,7 @@ mapConcurrently_ f t = unsafeEff $ \es -> do
306320
307321-- | Lifted 'A.forConcurrently'.
308322forConcurrently
309− :: (Traversable f, Concurrent :> es)
323+ :: (Traversable f, AsyncE :> es)
310324 => f a
311325 -> (a -> Eff es b)
312326 -> Eff es (f b)
@@ -315,7 +329,7 @@ forConcurrently t f = unsafeEff $ \es -> do
315329
316330-- | Lifted 'A.forConcurrently_'.
317331forConcurrently_
318− :: (Foldable f, Concurrent :> es)
332+ :: (Foldable f, AsyncE :> es)
319333 => f a
320334 -> (a -> Eff es b)
321335 -> Eff es ()
@@ -323,12 +337,12 @@ forConcurrently_ t f = unsafeEff $ \es -> do
323337 U.forConcurrently_ t (\a -> unEff (f a) =<< cloneEnv es)
324338
325339-- | Lifted 'A.replicateConcurrently'.
326−replicateConcurrently :: Concurrent :> es => Int -> Eff es a -> Eff es [a]
340+replicateConcurrently :: AsyncE :> es => Int -> Eff es a -> Eff es [a]
327341replicateConcurrently n f = unsafeEff $ \es -> do
328342 U.replicateConcurrently n (unEff f =<< cloneEnv es)
329343
330344-- | Lifted 'A.replicateConcurrently_'.
331−replicateConcurrently_ :: Concurrent :> es => Int -> Eff es a -> Eff es ()
345+replicateConcurrently_ :: AsyncE :> es => Int -> Eff es a -> Eff es ()
332346replicateConcurrently_ n f = unsafeEff $ \es -> do
333347 U.replicateConcurrently_ n (unEff f =<< cloneEnv es)
334348
@@ -337,7 +351,7 @@ replicateConcurrently_ n f = unsafeEff $ \es -> do
337351
338352-- | Lifted 'U.pooledMapConcurrentlyN'.
339353pooledMapConcurrentlyN
340− :: (Concurrent :> es, Traversable t)
354+ :: (AsyncE :> es, Traversable t)
341355 => Int
342356 -> (a -> Eff es b)
343357 -> t a
@@ -347,7 +361,7 @@ pooledMapConcurrentlyN threads f t = unsafeEff $ \es -> do
347361
348362-- | Lifted 'U.pooledMapConcurrently'.
349363pooledMapConcurrently
350− :: (Concurrent :> es, Traversable t)
364+ :: (AsyncE :> es, Traversable t)
351365 => (a -> Eff es b)
352366 -> t a
353367 -> Eff es (t b)
@@ -356,7 +370,7 @@ pooledMapConcurrently f t = unsafeEff $ \es -> do
356370
357371-- | Lifted 'U.pooledMapConcurrentlyN'.
358372pooledMapConcurrentlyN_
359− :: (Concurrent :> es, Foldable f)
373+ :: (AsyncE :> es, Foldable f)
360374 => Int
361375 -> (a -> Eff es b)
362376 -> f a
@@ -366,7 +380,7 @@ pooledMapConcurrentlyN_ threads f t = unsafeEff $ \es -> do
366380
367381-- | Lifted 'U.pooledMapConcurrently_'.
368382pooledMapConcurrently_
369− :: (Concurrent :> es, Foldable f)
383+ :: (AsyncE :> es, Foldable f)
370384 => (a -> Eff es b)
371385 -> f a
372386 -> Eff es ()
@@ -375,7 +389,7 @@ pooledMapConcurrently_ f t = unsafeEff $ \es -> do
375389
376390-- | Lifted 'U.pooledForConcurrentlyN'.
377391pooledForConcurrentlyN
378− :: (Concurrent :> es, Traversable t)
392+ :: (AsyncE :> es, Traversable t)
379393 => Int
380394 -> t a
381395 -> (a -> Eff es b)
@@ -385,7 +399,7 @@ pooledForConcurrentlyN threads t f = unsafeEff $ \es -> do
385399
386400-- | Lifted 'U.pooledForConcurrently'.
387401pooledForConcurrently
388− :: (Concurrent :> es, Traversable t)
402+ :: (AsyncE :> es, Traversable t)
389403 => t a
390404 -> (a -> Eff es b)
391405 -> Eff es (t b)
@@ -394,7 +408,7 @@ pooledForConcurrently t f = unsafeEff $ \es -> do
394408
395409-- | Lifted 'U.pooledForConcurrentlyN'.
396410pooledForConcurrentlyN_
397− :: (Concurrent :> es, Foldable f)
411+ :: (AsyncE :> es, Foldable f)
398412 => Int
399413 -> f a
400414 -> (a -> Eff es b)
@@ -404,7 +418,7 @@ pooledForConcurrentlyN_ threads t f = unsafeEff $ \es -> do
404418
405419-- | Lifted 'U.pooledForConcurrently_'.
406420pooledForConcurrently_
407− :: (Concurrent :> es, Foldable f)
421+ :: (AsyncE :> es, Foldable f)
408422 => f a
409423 -> (a -> Eff es b)
410424 -> Eff es ()
@@ -412,22 +426,22 @@ pooledForConcurrently_ t f = unsafeEff $ \es -> do
412426 U.pooledForConcurrently_ t (\a -> unEff (f a) =<< cloneEnv es)
413427
414428-- | Lifted 'U.pooledReplicateConcurrentlyN'.
415−pooledReplicateConcurrentlyN :: Concurrent :> es => Int -> Int -> Eff es a -> Eff es [a]
429+pooledReplicateConcurrentlyN :: AsyncE :> es => Int -> Int -> Eff es a -> Eff es [a]
416430pooledReplicateConcurrentlyN threads n f = unsafeEff $ \es -> do
417431 U.pooledReplicateConcurrentlyN threads n (unEff f =<< cloneEnv es)
418432
419433-- | Lifted 'U.pooledReplicateConcurrently'.
420−pooledReplicateConcurrently :: Concurrent :> es => Int -> Eff es a -> Eff es [a]
434+pooledReplicateConcurrently :: AsyncE :> es => Int -> Eff es a -> Eff es [a]
421435pooledReplicateConcurrently n f = unsafeEff $ \es -> do
422436 U.pooledReplicateConcurrently n (unEff f =<< cloneEnv es)
423437
424438-- | Lifted 'U.pooledReplicateConcurrentlyN_'.
425−pooledReplicateConcurrentlyN_ :: Concurrent :> es => Int -> Int -> Eff es a -> Eff es ()
439+pooledReplicateConcurrentlyN_ :: AsyncE :> es => Int -> Int -> Eff es a -> Eff es ()
426440pooledReplicateConcurrentlyN_ threads n f = unsafeEff $ \es -> do
427441 U.pooledReplicateConcurrentlyN_ threads n (unEff f =<< cloneEnv es)
428442
429443-- | Lifted 'U.pooledReplicateConcurrently_'.
430−pooledReplicateConcurrently_ :: Concurrent :> es => Int -> Eff es a -> Eff es ()
444+pooledReplicateConcurrently_ :: AsyncE :> es => Int -> Eff es a -> Eff es ()
431445pooledReplicateConcurrently_ n f = unsafeEff $ \es -> do
432446 U.pooledReplicateConcurrently_ n (unEff f =<< cloneEnv es)
433447
@@ -435,7 +449,7 @@ pooledReplicateConcurrently_ n f = unsafeEff $ \es -> do
435449-- Conc
436450
437451-- | Lifted 'U.Conc'.
438−data Conc :: [Effect] -> Type -> Type where
452+data Conc es a where
439453 Action :: Eff es a -> Conc es a
440454 Apply :: Conc es (v -> a) -> Conc es v -> Conc es a
441455 LiftA2 :: (x -> y -> a) -> Conc es x -> Conc es y -> Conc es a
@@ -467,7 +481,7 @@ conc :: Eff es a -> Conc es a
467481conc = Action
468482
469483-- | Lifted 'U.runConc'.
470−runConc :: Concurrent :> es => Conc es a -> Eff es a
484+runConc :: AsyncE :> es => Conc es a -> Eff es a
471485runConc m = unsafeEff $ \es -> U.runConc (unliftConc es m)
472486 where
473487 unliftConc :: Env es -> Conc es a -> U.Conc IO a
@@ -488,20 +502,20 @@ newtype Concurrently es a = Concurrently { runConcurrently :: Eff es a }
488502instance Functor (Concurrently es) where
489503 fmap f (Concurrently a) = Concurrently (fmap f a)
490504
491−instance Concurrent :> es => Applicative (Concurrently es) where
505+instance AsyncE :> es => Applicative (Concurrently es) where
492506 pure = Concurrently . pure
493507 Concurrently fs <*> Concurrently as =
494508 Concurrently ((\(f, a) -> f a) <$> concurrently fs as)
495509
496−instance Concurrent :> es => Alternative (Concurrently es) where
510+instance AsyncE :> es => Alternative (Concurrently es) where
497511 empty = Concurrently . unsafeEff_ . forever $ threadDelay maxBound
498512 Concurrently as <|> Concurrently bs =
499513 Concurrently (either id id <$> race as bs)
500514
501−instance (Concurrent :> es, Semigroup a) => Semigroup (Concurrently es a) where
515+instance (AsyncE :> es, Semigroup a) => Semigroup (Concurrently es a) where
502516 (<>) = liftA2 (<>)
503517
504−instance (Concurrent :> es, Monoid a) => Monoid (Concurrently es a) where
518+instance (AsyncE :> es, Monoid a) => Monoid (Concurrently es a) where
505519 mempty = pure mempty
506520
507521----------------------------------------
@@ -519,9 +533,10 @@ liftAsyncWithUnmask
519533 :: (((forall b. IO b -> IO b) -> IO a) -> IO (Async a))
520534 -> ((forall b. Eff es b -> Eff es b) -> Eff es a)
521535 -> Eff es (Async a)
522−liftAsyncWithUnmask fork action = unsafeEff $ \es -> do
523− esA <- cloneEnv es
524− fork $ \unmask -> unEff (action $ unsafeLiftMapIO unmask) esA
536+liftAsyncWithUnmask fork action = do
537+ unsafeWithLiftMapIO $ \liftMap -> unsafeEff $ \es -> do
538+ esA <- cloneEnv es
539+ fork $ \unmask -> unEff (action $ liftMap unmask) esA
525540
526541liftWithAsync
527542 :: (IO a -> (Async a -> IO b) -> IO b)
@@ -538,7 +553,8 @@ liftWithAsyncWithUnmask
538553 -> ((forall c. Eff es c -> Eff es c) -> Eff es a)
539554 -> (Async a -> Eff es b)
540555 -> Eff es b
541−liftWithAsyncWithUnmask withA action k = unsafeEff $ \es -> do
542− esA <- cloneEnv es
543− withA (\unmask -> unEff (action $ unsafeLiftMapIO unmask) esA)
544− (\a -> unEff (k a) es)
556+liftWithAsyncWithUnmask withA action k = do
557+ unsafeWithLiftMapIO $ \liftMap -> unsafeEff $ \es -> do
558+ esA <- cloneEnv es
559+ withA (\unmask -> unEff (action $ liftMap unmask) esA)
560+ (\a -> unEff (k a) es)