Skip to content

Commit 71676af

Browse files
committed
Fixes #7, fixes #6, fixes #3, fixes #1
1 parent e1da7fb commit 71676af

File tree

6 files changed

+680
-447
lines changed

6 files changed

+680
-447
lines changed

MODULES.md

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,29 @@
22

33
## Module Control.Monad.Aff
44

5-
#### `Async`
6-
7-
``` purescript
8-
data Async :: !
9-
```
10-
11-
The effect of being asynchronous.
12-
13-
#### `EffA`
14-
15-
``` purescript
16-
type EffA e a = Eff (async :: Async | e) a
17-
```
18-
19-
The `Eff` type for a computation which has asynchronous effects.
20-
215
#### `Aff`
226

237
``` purescript
24-
newtype Aff e a
8+
data Aff :: # ! -> * -> *
259
```
2610

2711
A computation with effects `e`. The computation either errors or
2812
produces a value of type `a`.
2913

30-
This is moral equivalent of `ErrorT (ContT Unit (EffA e)) a`.
14+
This is moral equivalent of `ErrorT (ContT Unit (Eff e)) a`.
3115

3216
#### `PureAff`
3317

3418
``` purescript
3519
type PureAff a = forall e. Aff e a
3620
```
3721

22+
A pure asynchronous computation, having no effects.
3823

3924
#### `launchAff`
4025

4126
``` purescript
42-
launchAff :: forall e a. Aff e a -> EffA e Unit
27+
launchAff :: forall e a. Aff e a -> Eff e Unit
4328
```
4429

4530
Converts the asynchronous computation into a synchronous one. All values
@@ -48,7 +33,7 @@ and errors are ignored.
4833
#### `runAff`
4934

5035
``` purescript
51-
runAff :: forall e a. (Error -> Eff e Unit) -> (a -> Eff e Unit) -> Aff e a -> EffA e Unit
36+
runAff :: forall e a. (Error -> Eff e Unit) -> (a -> Eff e Unit) -> Aff e a -> Eff e Unit
5237
```
5338

5439
Runs the asynchronous computation. You must supply an error callback and a
@@ -57,7 +42,7 @@ success callback.
5742
#### `makeAff`
5843

5944
``` purescript
60-
makeAff :: forall e a. ((Error -> Eff e Unit) -> (a -> Eff e Unit) -> EffA e Unit) -> Aff e a
45+
makeAff :: forall e a. ((Error -> Eff e Unit) -> (a -> Eff e Unit) -> Eff e Unit) -> Aff e a
6146
```
6247

6348
Creates an asynchronous effect from a function that accepts error and
@@ -69,6 +54,14 @@ success callbacks.
6954
later :: forall e a. Aff e a -> Aff e a
7055
```
7156

57+
Runs the asynchronous computation off the current execution context.
58+
59+
#### `later'`
60+
61+
``` purescript
62+
later' :: forall e a. Number -> Aff e a -> Aff e a
63+
```
64+
7265
Runs the asynchronous computation later (off the current execution context).
7366

7467
#### `forkAff`

README.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,18 @@ deleteBlankLines path =
3535
saveFile path contents'
3636
```
3737

38-
This looks like ordinary, synchronous, imperative code, but actually operates asynchronously without any callbacks (error handling is baked in so you only deal with it when you want to).
38+
This looks like ordinary, synchronous, imperative code, but actually operates asynchronously without any callbacks. Error handling is baked in so you only deal with it when you want to.
3939

40-
The library contains instances for `Semigroup`, `Monoid`, `Apply`, `Applicative`, `Bind`, `Monad`, `Alt`, `Plus`, `MonadPlus`, `MonadEff`, and `MonadError`. These instances allow you to compose `Aff`-ectful code as easily as `Eff`, as well as interop with existing `Eff` code.
40+
The library contains instances for `Semigroup`, `Monoid`, `Apply`, `Applicative`, `Bind`, `Monad`, `Alt`, `Plus`, `MonadPlus`, `MonadEff`, and `MonadError`. These instances allow you to compose asynchronous code as easily as `Eff`, as well as interop with existing `Eff` code.
4141

4242
## Escaping Callback Hell
4343

4444
Hopefully, you're using libraries that already use the `Aff` type, so you don't even have to think about callbacks!
4545

46-
If you're building your own library, or you have to interact with some native code that expects callbacks, then *purescript-aff* provides a `makeAff` function you can use:
46+
If you're building your own library, or you have to interact with some native code that expects callbacks, then *purescript-aff* provides a `makeAff` function:
4747

4848
```purescript
49-
makeAff :: forall e a. ((Error -> Eff e Unit) -> (a -> Eff e Unit) -> EffA e Unit) -> Aff e a
49+
makeAff :: forall e a. ((Error -> Eff e Unit) -> (a -> Eff e Unit) -> Eff e Unit) -> Aff e a
5050
```
5151

5252
This function expects you to provide a handler, which should call a user-supplied error callback or success callback with the result of the asynchronous computation.
@@ -64,7 +64,7 @@ function ajaxGet(callback) { // accepts a callback
6464
}
6565
}
6666
}
67-
""" :: forall e. (Response -> Eff e Unit) -> Request -> EffA e Unit
67+
""" :: forall e. (Response -> Eff e Unit) -> Request -> Eff e Unit
6868
```
6969

7070
We can wrap this into an asynchronous computation like so:
@@ -142,7 +142,7 @@ These are defined in [purescript-transformers](http://github.com/purescript/pure
142142
Here's an example of how you can use them:
143143

144144
```purescript
145-
do resp <- (Ajax.get "http://foo.com") `catchError` (\e -> pure defaultResponse)
145+
do resp <- (Ajax.get "http://foo.com") `catchError` (const $ pure defaultResponse)
146146
if resp.statusCode != 200 then throwError myErr
147147
else pure resp.body
148148
```
@@ -162,6 +162,15 @@ Because Javascript is single-threaded, forking does not actually cause the
162162
computation to be run in a separate thread. Forking just allows the subsequent
163163
actions to execute without waiting for the forked computation to complete.
164164

165+
If the asynchronous computation supports it, you can "kill" a forked computation
166+
using the returned canceler:
167+
168+
```purescript
169+
canceler <- forkAff myAff
170+
canceled <- canceler
171+
_ <- liftEff $ if canceled then (trace "Canceled") else (trace "Not Canceled")
172+
```
173+
165174
## Queues
166175

167176
The `Control.Monad.Aff.Queue` module contains asynchronous queues. These can
@@ -175,7 +184,7 @@ do v <- makeQueue
175184
```
176185

177186
You can use these constructs as one-sided blocking queues, which suspend (if
178-
necessary) on `take operations, or as asynchronous variables (similar to
187+
necessary) on `take` operations, or as asynchronous variables (similar to
179188
Haskell's `MVar` construct).
180189

181190
## Parallel Execution

examples/src/Examples.purs

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,13 @@ module Examples where
1212
import Control.Monad.Eff.Exception(error)
1313
import Control.Monad.Error.Class(throwError)
1414

15-
foreign import data Time :: !
16-
17-
foreign import timeout """
18-
function timeout(time) {
19-
return function(error) {
20-
return function(success) {
21-
return function() {
22-
setTimeout(function() {
23-
try {
24-
success({})();
25-
} catch (e) {
26-
error(e)();
27-
}
28-
}, time);
29-
}
30-
}
31-
}
32-
}
33-
""" :: forall e. Number -> Aff (time :: Time | e) Unit
34-
3515
type Test = forall e. Aff (trace :: Trace | e) Unit
3616
type TestQueue = forall e. Aff (trace :: Trace, queue :: QueueFx | e) Unit
37-
type TestQueueTime = forall e. Aff (trace :: Trace, queue :: QueueFx, time :: Time | e) Unit
3817

39-
test_sequencing :: forall e. Number -> Aff (trace :: Trace, time :: Time | e) Unit
18+
test_sequencing :: Number -> Test
4019
test_sequencing 0 = liftEff $ trace "Done"
4120
test_sequencing n = do
42-
timeout 100
43-
liftEff $ trace (show (n / 10) ++ " seconds left")
21+
later' 100 (liftEff $ trace (show (n / 10) ++ " seconds left"))
4422
test_sequencing (n - 1)
4523

4624
test_pure :: Test
@@ -74,22 +52,22 @@ module Examples where
7452
e <- attempt $ takeQueue v
7553
liftEff $ either (const $ trace "Success: Killed queue dead") (const $ trace "Failure: Oh noes, queue survived!") e
7654

77-
test_parRace :: TestQueueTime
55+
test_parRace :: TestQueue
7856
test_parRace = do
79-
s <- runPar (Par (timeout 100 *> pure "Success: Early bird got the worm") <|>
80-
Par (timeout 200 *> pure "Failure: Late bird got the worm"))
57+
s <- runPar (Par (later' 100 $ pure "Success: Early bird got the worm") <|>
58+
Par (later' 200 $ pure "Failure: Late bird got the worm"))
8159
liftEff $ trace s
8260

83-
test_parRaceKill1 :: TestQueueTime
61+
test_parRaceKill1 :: TestQueue
8462
test_parRaceKill1 = do
85-
s <- runPar (Par (timeout 100 *> throwError (error ("Oh noes!"))) <|>
86-
Par (timeout 200 *> pure "Success: Early error was ignored in favor of late success"))
63+
s <- runPar (Par (later' 100 $ throwError (error ("Oh noes!"))) <|>
64+
Par (later' 200 $ pure "Success: Early error was ignored in favor of late success"))
8765
liftEff $ trace s
8866

89-
test_parRaceKill2 :: TestQueueTime
67+
test_parRaceKill2 :: TestQueue
9068
test_parRaceKill2 = do
91-
e <- attempt $ runPar (Par (timeout 100 *> throwError (error ("Oh noes!"))) <|>
92-
Par (timeout 200 *> throwError (error ("Oh noes!"))))
69+
e <- attempt $ runPar (Par (later' 100 $ throwError (error ("Oh noes!"))) <|>
70+
Par (later' 200 $ throwError (error ("Oh noes!"))))
9371
liftEff $ either (const $ trace "Success: Killing both kills it dead") (const $ trace "Failure: It's alive!!!") e
9472

9573
main = launchAff $ do
@@ -122,3 +100,5 @@ module Examples where
122100

123101
liftEff $ trace "Testing Par (<|>) - kill two"
124102
test_parRaceKill2
103+
104+
liftEff $ trace "Done testing"

0 commit comments

Comments
 (0)