on master help sign in
Documentation update
e519afbAndrzej Rybczak
src/Effectful/Async.hs+1−1
@@ -67,7 +67,7 @@ import Effectful.Internal.Monad
67-- | Run 'Eff' computations asynchronously using the @async@ library.
67-- | Run 'Eff' computations asynchronously using the @async@ library.
68--
68--
69-- /Note:/ thread local state changes in 'Eff' computations run asynchronously
69-- /Note:/ thread local state changes in 'Eff' computations run asynchronously
70−-- as 'Async' will not affect the parent thread.
70+-- will not affect the parent thread.
71data AsyncE :: Effect where
71data AsyncE :: Effect where
72 AsyncE :: AsyncE m r
72 AsyncE :: AsyncE m r
73
73
src/Effectful/Internal/Monad.hs+27−18
@@ -9,11 +9,11 @@ module Effectful.Internal.Monad
9 ( -- * Monad
9 ( -- * Monad
10 Eff(..)
10 Eff(..)
11 , runEff
11 , runEff
12− , unsafeEff
13− , unsafeEff_
14
12
15− -- ** Running in 'IO'
13+ -- ** Access to the internal representation
16 , RunIn
14 , RunIn
15+ , unsafeEff
16+ , unsafeEff_
17 , unsafeUnliftEff
17 , unsafeUnliftEff
18
18
19 -- * IO
19 -- * IO
@@ -62,36 +62,45 @@ runEff (Eff m) =
62 -- cleanup actions to run, so the "Dupable" part should also be just fine.
62 -- cleanup actions to run, so the "Dupable" part should also be just fine.
63 unsafeDupablePerformIO $ m =<< emptyEnv
63 unsafeDupablePerformIO $ m =<< emptyEnv
64
64
65+----------------------------------------
66+
67+-- | Access underlying 'IO' monad along with the environment.
65unsafeEff :: (Env es -> IO a) -> Eff es a
68unsafeEff :: (Env es -> IO a) -> Eff es a
66unsafeEff m = Eff (oneShot m)
69unsafeEff m = Eff (oneShot m)
67
70
71+-- | Access underlying 'IO' monad.
68unsafeEff_ :: IO a -> Eff es a
72unsafeEff_ :: IO a -> Eff es a
69unsafeEff_ m = unsafeEff $ \_ -> m
73unsafeEff_ m = unsafeEff $ \_ -> m
70
74
71−----------------------------------------
72−
73-- | A function that runs 'Eff' computations in @m@ (usually a local 'Eff'
75-- | A function that runs 'Eff' computations in @m@ (usually a local 'Eff'
74-- environment or 'IO').
76-- environment or 'IO').
75type RunIn es m = forall r. Eff es r -> m r
77type RunIn es m = forall r. Eff es r -> m r
76
78
77-- | Lower 'Eff' computations into 'IO'.
79-- | Lower 'Eff' computations into 'IO'.
80+--
81+-- /Note:/ the 'RunIn' argument has to be called from the same thread as
82+-- 'unsafeUnliftEff' ('liftBaseWith' / 'withRunInIO'). Attempting otherwise
83+-- results in a runtime error, because it cannot be done safely in general
84+-- (*). If you need to spawn threads, have a look at "Effectful.Async" or create
85+-- a new 'Eff' environment.
86+--
87+-- (*) Consider the following:
88+--
89+-- @
90+-- runState 'x' $ do
91+-- liftBaseWith $ \run -> forkIO $ do
92+-- threadDelay 1000000
93+-- run $ ... (1)
94+-- ... (2)
95+-- ...
96+-- @
97+--
98+-- If (1) runs after (2) completed, the State Char effect is no longer in scope,
99+-- but (1) assumes otherwise and things break horribly.
78unsafeUnliftEff :: (RunIn es IO -> IO a) -> Eff es a
100unsafeUnliftEff :: (RunIn es IO -> IO a) -> Eff es a
79unsafeUnliftEff f = unsafeEff $ \es -> do
101unsafeUnliftEff f = unsafeEff $ \es -> do
80 tid0 <- myThreadId
102 tid0 <- myThreadId
81 f $ \(Eff m) -> do
103 f $ \(Eff m) -> do
82− -- The unlifting function can't be safely called from another thread.
83− --
84− -- Consider the following:
85− --
86− -- runState 'x' $ do
87− -- liftBaseWith $ \run -> forkIO $ do
88− -- threadDelay 1000000
89− -- run $ ... (1)
90− -- ... (2)
91− -- ...
92− --
93− -- If (1) runs after (2) completed, the State Char effect is no longer in
94− -- scope, but (1) assumes otherwise and things break horribly.
95 tid <- myThreadId
104 tid <- myThreadId
96 if tid == tid0
105 if tid == tid0
97 then m es
106 then m es