Skip to content

Commit 73cff86

Browse files
committed
Add forkAll combinator
1 parent e239f53 commit 73cff86

File tree

7 files changed

+91
-41
lines changed

7 files changed

+91
-41
lines changed

docs/Control.Monad.Aff.Class.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ class MonadAff e m where
99

1010
##### Instances
1111
``` purescript
12-
instance monadAffAff :: MonadAff e (Aff e)
13-
instance monadAffContT :: (Monad m, MonadAff eff m) => MonadAff eff (ContT r m)
14-
instance monadAffExceptT :: (Monad m, MonadAff eff m) => MonadAff eff (ExceptT e m)
15-
instance monadAffListT :: (Monad m, MonadAff eff m) => MonadAff eff (ListT m)
16-
instance monadAffMaybe :: (Monad m, MonadAff eff m) => MonadAff eff (MaybeT m)
17-
instance monadAffReader :: (Monad m, MonadAff eff m) => MonadAff eff (ReaderT r m)
18-
instance monadAffRWS :: (Monad m, Monoid w, MonadAff eff m) => MonadAff eff (RWST r w s m)
19-
instance monadAffState :: (Monad m, MonadAff eff m) => MonadAff eff (StateT s m)
20-
instance monadAffWriter :: (Monad m, Monoid w, MonadAff eff m) => MonadAff eff (WriterT w m)
12+
MonadAff e (Aff e)
13+
(Monad m, MonadAff eff m) => MonadAff eff (ContT r m)
14+
(Monad m, MonadAff eff m) => MonadAff eff (ExceptT e m)
15+
(Monad m, MonadAff eff m) => MonadAff eff (ListT m)
16+
(Monad m, MonadAff eff m) => MonadAff eff (MaybeT m)
17+
(Monad m, MonadAff eff m) => MonadAff eff (ReaderT r m)
18+
(Monad m, Monoid w, MonadAff eff m) => MonadAff eff (RWST r w s m)
19+
(Monad m, MonadAff eff m) => MonadAff eff (StateT s m)
20+
(Monad m, Monoid w, MonadAff eff m) => MonadAff eff (WriterT w m)
2121
```
2222

2323

docs/Control.Monad.Aff.Console.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#### `log`
44

55
``` purescript
6-
log :: forall e. String -> Aff (console :: CONSOLE | e) String
6+
log :: forall e. String -> Aff (console :: CONSOLE | e) Unit
77
```
88

99
Logs any string to the console. This basically saves you
@@ -12,10 +12,10 @@ from writing `liftEff $ log x` everywhere.
1212
#### `print`
1313

1414
``` purescript
15-
print :: forall e a. (Show a) => a -> Aff (console :: CONSOLE | e) a
15+
print :: forall e a. (Show a) => a -> Aff (console :: CONSOLE | e) Unit
1616
```
1717

18-
Prints any `Show`-able value to the console. This basically saves you
18+
Prints any `Show`-able value to the console. This basically saves you
1919
from writing `liftEff $ print x` everywhere.
2020

2121

docs/Control.Monad.Aff.Par.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
## Module Control.Monad.Aff.Par
22

3-
A newtype over `Aff` that provides `Applicative` instances that run in
4-
parallel. This is useful, for example, if you want to run a whole bunch
3+
A newtype over `Aff` that provides `Applicative` instances that run in
4+
parallel. This is useful, for example, if you want to run a whole bunch
55
of AJAX requests at the same time, rather than sequentially.
66

77
#### `Par`
@@ -13,14 +13,14 @@ newtype Par e a
1313

1414
##### Instances
1515
``` purescript
16-
instance semigroupPar :: (Semigroup a) => Semigroup (Par e a)
17-
instance monoidPar :: (Monoid a) => Monoid (Par e a)
18-
instance functorPar :: Functor (Par e)
19-
instance applyPar :: Apply (Par e)
20-
instance applicativePar :: Applicative (Par e)
21-
instance altPar :: Alt (Par e)
22-
instance plusPar :: Plus (Par e)
23-
instance alternativePar :: Alternative (Par e)
16+
(Semigroup a) => Semigroup (Par e a)
17+
(Monoid a) => Monoid (Par e a)
18+
Functor (Par e)
19+
Apply (Par e)
20+
Applicative (Par e)
21+
Alt (Par e)
22+
Plus (Par e)
23+
Alternative (Par e)
2424
```
2525

2626
#### `runPar`

docs/Control.Monad.Aff.md

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@ This is moral equivalent of `ErrorT (ContT Unit (Eff e)) a`.
1313

1414
##### Instances
1515
``` purescript
16-
instance semigroupAff :: (Semigroup a) => Semigroup (Aff e a)
17-
instance monoidAff :: (Monoid a) => Monoid (Aff e a)
18-
instance functorAff :: Functor (Aff e)
19-
instance applyAff :: Apply (Aff e)
20-
instance applicativeAff :: Applicative (Aff e)
21-
instance bindAff :: Bind (Aff e)
22-
instance monadAff :: Monad (Aff e)
23-
instance monadEffAff :: MonadEff e (Aff e)
24-
instance monadErrorAff :: MonadError Error (Aff e)
25-
instance altAff :: Alt (Aff e)
26-
instance plusAff :: Plus (Aff e)
27-
instance alternativeAff :: Alternative (Aff e)
28-
instance monadPlusAff :: MonadPlus (Aff e)
29-
instance monadRecAff :: MonadRec (Aff e)
30-
instance monadContAff :: MonadCont (Aff e)
16+
(Semigroup a) => Semigroup (Aff e a)
17+
(Monoid a) => Monoid (Aff e a)
18+
Functor (Aff e)
19+
Apply (Aff e)
20+
Applicative (Aff e)
21+
Bind (Aff e)
22+
Monad (Aff e)
23+
MonadEff e (Aff e)
24+
MonadError Error (Aff e)
25+
Alt (Aff e)
26+
Plus (Aff e)
27+
Alternative (Aff e)
28+
MonadPlus (Aff e)
29+
MonadRec (Aff e)
30+
MonadCont (Aff e)
3131
```
3232

3333
#### `PureAff`
@@ -54,8 +54,8 @@ successfully canceled. The flag should not be used for communication.
5454

5555
##### Instances
5656
``` purescript
57-
instance semigroupCanceler :: Semigroup (Canceler e)
58-
instance monoidCanceler :: Monoid (Canceler e)
57+
Semigroup (Canceler e)
58+
Monoid (Canceler e)
5959
```
6060

6161
#### `cancel`
@@ -159,6 +159,16 @@ will not block on the result of the computation.
159159
Returns a canceler that can be used to attempt cancellation of the
160160
forked computation.
161161

162+
#### `forkAll`
163+
164+
``` purescript
165+
forkAll :: forall f e a. (Foldable f) => f (Aff e a) -> Aff e Unit
166+
```
167+
168+
Forks many asynchronous computation at once, ignoring the results.
169+
170+
This function is stack-safe up to the selected Foldable instance.
171+
162172
#### `attempt`
163173

164174
``` purescript

src/Control/Monad/Aff.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,26 @@ exports._forkAff = function (nonCanceler, aff) {
9696
};
9797
}
9898

99+
exports._forkAll = function (nonCanceler, foldl, affs) {
100+
var voidF = function(){};
101+
102+
return function(success, error) {
103+
foldl(function(_) {
104+
return function(aff) {
105+
aff(voidF, voidF);
106+
};
107+
})({})(affs);
108+
109+
try {
110+
success({});
111+
} catch(e) {
112+
error(e);
113+
}
114+
115+
return nonCanceler;
116+
};
117+
}
118+
99119
exports._makeAff = function (cb) {
100120
return function(success, error) {
101121
return cb(function(e) {

src/Control/Monad/Aff.purs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module Control.Monad.Aff
88
, cancelWith
99
, finally
1010
, forkAff
11+
, forkAll
1112
, later
1213
, later'
1314
, launchAff
@@ -33,6 +34,7 @@ import Control.MonadPlus (MonadPlus)
3334
import Control.Plus (Plus)
3435

3536
import Data.Either (Either(..), either)
37+
import Data.Foldable (Foldable, foldl)
3638
import Data.Function (Fn2(), Fn3(), runFn2, runFn3)
3739
import Data.Monoid (Monoid, mempty)
3840

@@ -120,6 +122,12 @@ finally aff1 aff2 = do
120122
forkAff :: forall e a. Aff e a -> Aff e (Canceler e)
121123
forkAff aff = runFn2 _forkAff nonCanceler aff
122124

125+
-- | Forks many asynchronous computation at once, ignoring the results.
126+
-- |
127+
-- | This function is stack-safe up to the selected Foldable instance.
128+
forkAll :: forall f e a. (Foldable f) => f (Aff e a) -> Aff e Unit
129+
forkAll affs = runFn3 _forkAll nonCanceler foldl affs
130+
123131
-- | Promotes any error to the value level of the asynchronous monad.
124132
attempt :: forall e a. Aff e a -> Aff e (Either Error a)
125133
attempt aff = runFn3 _attempt Left Right aff
@@ -207,6 +215,8 @@ foreign import _unsafeInterleaveAff :: forall e1 e2 a. Aff e1 a -> Aff e2 a
207215

208216
foreign import _forkAff :: forall e a. Fn2 (Canceler e) (Aff e a) (Aff e (Canceler e))
209217

218+
foreign import _forkAll :: forall f e a b. Fn3 (Canceler e) ((b -> a -> b) -> b -> f a -> b) (f (Aff e a)) (Aff e Unit)
219+
210220
foreign import _makeAff :: forall e a. ((Error -> Eff e Unit) -> (a -> Eff e Unit) -> Eff e (Canceler e)) -> Aff e a
211221

212222
foreign import _pure :: forall e a. Fn2 (Canceler e) a (Aff e a)

test/Test/Main.purs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ module Test.Main where
22

33
import Prelude
44

5-
import Control.Monad.Aff (Aff(), runAff, later')
5+
import Control.Monad.Aff (Aff(), runAff, later', forkAll)
6+
import Control.Monad.Aff.AVar (AVAR(), makeVar', modifyVar, takeVar)
67
import Control.Monad.Cont.Class (callCC)
78
import Control.Monad.Eff (Eff())
89
import Control.Monad.Eff.Class (liftEff)
910
import Control.Monad.Eff.Console (CONSOLE(), log, print)
1011
import Control.Monad.Eff.Exception (EXCEPTION(), throwException)
1112
import Control.Monad.Rec.Class (tailRecM)
1213

14+
import Data.Array ((..))
1315
import Data.Either (Either(..))
1416

1517
loop :: forall eff. Int -> Aff (console :: CONSOLE | eff) Unit
@@ -20,13 +22,21 @@ loop n = tailRecM go n
2022
return (Right unit)
2123
go n = return (Left (n - 1))
2224

25+
all :: forall eff. Int -> Aff (console :: CONSOLE, avar :: AVAR | eff) Unit
26+
all n = do
27+
var <- makeVar' 0
28+
forkAll $ map (\_ -> modifyVar (+ 1) var) (1 .. n)
29+
count <- takeVar var
30+
liftEff $ log ("Forked " <> show count)
31+
2332
delay :: forall eff. Int -> Aff eff Unit
2433
delay n = callCC \cont ->
2534
later' n (cont unit)
2635

27-
main :: Eff (console :: CONSOLE, err :: EXCEPTION) Unit
36+
main :: Eff (console :: CONSOLE, avar :: AVAR, err :: EXCEPTION) Unit
2837
main = runAff throwException (const (pure unit)) $ do
2938
liftEff $ log "pre-delay"
3039
delay 1000
3140
liftEff $ log "post-delay"
3241
loop 1000000
42+
all 100000

0 commit comments

Comments
 (0)