Skip to content

Commit 6e23d0a

Browse files
committed
Use catchError primitive instead of attempt
1 parent b53ec1e commit 6e23d0a

File tree

4 files changed

+62
-61
lines changed

4 files changed

+62
-61
lines changed

src/Control/Monad/Aff.purs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module Control.Monad.Aff
22
( module Internal
3+
, module Control.Monad.Error.Class
34
, liftEff'
45
, forkAff
56
, runAff
@@ -8,19 +9,20 @@ module Control.Monad.Aff
89
) where
910

1011
import Prelude
11-
import Control.Monad.Aff.Internal (ASYNC, Aff, Thread(..), attempt, launchAff, unsafeLaunchAff)
12-
import Control.Monad.Aff.Internal (Aff, ParAff, Thread, Canceler(..), ASYNC, attempt, bracket, delay, launchAff, makeAff, nonCanceler) as Internal
12+
import Control.Monad.Aff.Internal (ASYNC, Aff, Thread(..), launchAff, unsafeLaunchAff)
13+
import Control.Monad.Aff.Internal (Aff, ParAff, Thread, Canceler(..), ASYNC, bracket, delay, launchAff, makeAff, nonCanceler) as Internal
1314
import Control.Monad.Eff (Eff)
1415
import Control.Monad.Eff.Class (liftEff)
1516
import Control.Monad.Eff.Exception (Error, EXCEPTION)
1617
import Control.Monad.Eff.Unsafe (unsafeCoerceEff)
18+
import Control.Monad.Error.Class (try)
1719
import Data.Either (Either)
1820

1921
liftEff' eff a. Eff (exception EXCEPTION | eff) a Aff eff a
2022
liftEff' = liftEff <<< unsafeCoerceEff
2123

2224
runAff eff a. (Either Error a Eff eff Unit) Aff eff a Eff (async ASYNC | eff) Unit
23-
runAff k aff = void $ launchAff $ liftEff <<< k =<< attempt aff
25+
runAff k aff = void $ launchAff $ liftEff <<< k =<< try aff
2426

2527
forkAff eff a. Aff eff a Aff eff (Thread eff a)
2628
forkAff = liftEff <<< unsafeLaunchAff

src/Control/Monad/Aff/Internal.js

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ data Aff eff a
1010
| Throw Error
1111
| Sync (Eff eff a)
1212
| Async ((Either Error a -> Eff eff Unit) -> Eff eff (Canceler eff))
13-
| forall b. Attempt (Aff eff b) ?(Either Error b -> a)
13+
| forall b. Catch (Error -> a) (Aff eff b) ?(b -> a)
1414
| forall b. Bracket (Aff eff b) (b -> Aff eff Unit) (b -> Aff eff a)
1515
1616
*/
17-
var PURE = "Pure";
18-
var THROW = "Throw";
19-
var SYNC = "Sync";
20-
var ASYNC = "Async";
21-
var BIND = "Bind";
22-
var ATTEMPT = "Attempt";
23-
var BRACKET = "Bracket";
17+
var PURE = "Pure";
18+
var THROW = "Throw";
19+
var SYNC = "Sync";
20+
var ASYNC = "Async";
21+
var BIND = "Bind";
22+
var CATCH = "Catch";
23+
var BRACKET = "Bracket";
2424

2525
// These are constructors used to implement the recover stack. We still use the
2626
// Aff constructor so that property offsets can always inline.
@@ -48,6 +48,12 @@ exports._throwError = function (error) {
4848
return new Aff(THROW, error);
4949
};
5050

51+
exports._catchError = function (aff) {
52+
return function (k) {
53+
return new Aff(CATCH, aff, k);
54+
};
55+
};
56+
5157
exports._map = function (f) {
5258
return function (aff) {
5359
if (aff.tag === PURE) {
@@ -74,10 +80,6 @@ exports.makeAff = function (k) {
7480
return new Aff(ASYNC, k);
7581
};
7682

77-
exports.attempt = function (aff) {
78-
return new Aff(ATTEMPT, aff);
79-
};
80-
8183
exports.bracket = function (acquire) {
8284
return function (release) {
8385
return function (k) {
@@ -257,8 +259,8 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
257259
break;
258260

259261
// Enqueue the current stack of binds and continue
260-
case ATTEMPT:
261-
attempts = new Aff(CONS, new Aff(RECOVER, bhead, btail), attempts);
262+
case CATCH:
263+
attempts = new Aff(CONS, new Aff(RECOVER, step._2, bhead, btail), attempts);
262264
bhead = null;
263265
btail = null;
264266
status = CONTINUE;
@@ -293,16 +295,22 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
293295
} else {
294296
attempt = attempts._1;
295297
switch (attempt.tag) {
296-
// We cannot recover from an interrupt. If we are able to recover
297-
// we should step directly (since the return value is an Either).
298+
// We cannot recover from an interrupt. Otherwise we should
299+
// continue stepping, or run the exception handler if an exception
300+
// was raised.
298301
case RECOVER:
299302
attempts = attempts._2;
300303
if (interrupt === null) {
301-
bhead = attempt._1;
302-
btail = attempt._2;
303-
status = BINDSTEP;
304-
step = fail || step;
305-
fail = null;
304+
bhead = attempt._2;
305+
btail = attempt._3;
306+
if (fail === null) {
307+
status = BINDSTEP;
308+
step = fromRight(step);
309+
} else {
310+
status = CONTINUE;
311+
step = attempt._1(fromLeft(fail));
312+
fail = null;
313+
}
306314
}
307315
break;
308316

@@ -356,7 +364,7 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
356364
tmp = false;
357365
for (var k in joins) {
358366
tmp = true;
359-
runJoin(step, joins[k]);
367+
runEff(joins[k](step));
360368
}
361369
joins = tmp;
362370
// If we have an unhandled exception, and no other thread has joined
@@ -462,21 +470,21 @@ exports._launchAff = function (isLeft, fromLeft, fromRight, left, right, aff) {
462470
};
463471
};
464472

465-
function runJoin (result, cb) {
473+
function runEff (eff) {
466474
try {
467-
cb(result)();
475+
eff();
468476
} catch (error) {
469477
setTimeout(function () {
470478
throw error;
471-
}, 0)
479+
}, 0);
472480
}
473481
}
474482

475483
function runSync (left, right, eff) {
476484
try {
477485
return right(eff());
478486
} catch (error) {
479-
return left(error)
487+
return left(error);
480488
}
481489
}
482490

src/Control/Monad/Aff/Internal.purs

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ module Control.Monad.Aff.Internal
77
, nonCanceler
88
, makeAff
99
, launchAff
10-
, attempt
1110
, bracket
1211
, delay
1312
, unsafeLaunchAff
@@ -22,7 +21,7 @@ import Control.Monad.Eff.Class (class MonadEff, liftEff)
2221
import Control.Monad.Eff.Exception (Error, error)
2322
import Control.Monad.Eff.Ref (newRef, readRef, writeRef)
2423
import Control.Monad.Eff.Ref.Unsafe (unsafeRunRef)
25-
import Control.Monad.Error.Class (class MonadError, class MonadThrow, throwError)
24+
import Control.Monad.Error.Class (class MonadError, class MonadThrow, throwError, catchError, try)
2625
import Control.Monad.Rec.Class (class MonadRec, Step(..))
2726
import Control.MonadPlus (class MonadPlus)
2827
import Control.MonadZero (class MonadZero)
@@ -55,11 +54,7 @@ instance monoidAff ∷ Monoid a ⇒ Monoid (Aff eff a) where
5554
mempty = pure mempty
5655

5756
instance altAffAlt (Aff eff) where
58-
alt a1 a2 = do
59-
res ← attempt a1
60-
case res of
61-
Left err → a2
62-
Right r → pure r
57+
alt a1 a2 = catchError a1 (const a2)
6358

6459
instance plusAffPlus (Aff eff) where
6560
empty = throwError (error "Always fails")
@@ -83,11 +78,7 @@ instance monadThrowAff ∷ MonadThrow Error (Aff eff) where
8378
throwError = _throwError
8479

8580
instance monadErrorAffMonadError Error (Aff eff) where
86-
catchError aff k = do
87-
res ← attempt aff
88-
case res of
89-
Left err → k err
90-
Right r → pure r
81+
catchError = _catchError
9182

9283
instance monadEffAffMonadEff eff (Aff eff) where
9384
liftEff = _liftEff
@@ -104,8 +95,8 @@ instance applyParAff ∷ Apply (ParAff eff) where
10495
Thread t1 ← unsafeLaunchAff ff
10596
Thread t2 ← unsafeLaunchAff fa
10697
Thread t3 ← unsafeLaunchAff do
107-
f ← attempt t1.join
108-
a ← attempt t2.join
98+
f ← try t1.join
99+
a ← try t2.join
109100
liftEff (k (f <*> a))
110101
pure $ Canceler \err →
111102
parSequence_
@@ -142,8 +133,8 @@ instance altParAff ∷ Alt (ParAff eff) where
142133
Nothing, Right _ → t.kill earlyError *> liftEff (k r)
143134
Just r', _ → t.kill earlyError *> liftEff (k r')
144135

145-
Thread t3 ← unsafeLaunchAff $ runK t2 =<< attempt t1.join
146-
Thread t4 ← unsafeLaunchAff $ runK t1 =<< attempt t2.join
136+
Thread t3 ← unsafeLaunchAff $ runK t2 =<< try t1.join
137+
Thread t4 ← unsafeLaunchAff $ runK t1 =<< try t2.join
147138

148139
pure $ Canceler \err →
149140
parSequence_
@@ -195,11 +186,11 @@ delay (Milliseconds n) = Fn.runFn2 _delay Right n
195186

196187
foreign import _pure eff a. a Aff eff a
197188
foreign import _throwError eff a. Error Aff eff a
189+
foreign import _catchError eff a. Aff eff a (Error Aff eff a) Aff eff a
198190
foreign import _map eff a b. (a b) Aff eff a Aff eff b
199191
foreign import _bind eff a b. Aff eff a (a Aff eff b) Aff eff b
200192
foreign import _delay a eff. Fn.Fn2 (Unit Either a Unit) Number (Aff eff Unit)
201193
foreign import _liftEff eff a. Eff eff a Aff eff a
202-
foreign import attempt eff a. Aff eff a Aff eff (Either Error a)
203194
foreign import bracket eff a b. Aff eff a (a Aff eff Unit) (a Aff eff b) Aff eff b
204195
foreign import makeAff eff a. ((Either Error a Eff eff Unit) Eff eff (Canceler eff)) Aff eff a
205196

test/Test/Main.purs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module Test.Main where
22

33
import Prelude
4-
import Control.Monad.Aff (Aff, Canceler(..), ASYNC, nonCanceler, runAff, launchAff, makeAff, attempt, bracket, delay, forkAff, joinThread, killThread)
4+
import Control.Monad.Aff (Aff, Canceler(..), ASYNC, nonCanceler, runAff, launchAff, makeAff, try, bracket, delay, forkAff, joinThread, killThread)
55
import Control.Monad.Eff (Eff)
66
import Control.Monad.Eff.Class (class MonadEff, liftEff)
77
import Control.Monad.Eff.Console (CONSOLE)
@@ -50,10 +50,10 @@ runAssertEq ∷ ∀ eff a. Eq a ⇒ String → a → TestAff eff a → TestEff e
5050
runAssertEq s a = runAff (assertEff s <<< map (eq a))
5151

5252
assertEq eff a. Eq a String a TestAff eff a TestAff eff Unit
53-
assertEq s a aff = liftEff <<< assertEff s <<< map (eq a) =<< attempt aff
53+
assertEq s a aff = liftEff <<< assertEff s <<< map (eq a) =<< try aff
5454

5555
assert eff. String TestAff eff Boolean TestAff eff Unit
56-
assert s aff = liftEff <<< assertEff s =<< attempt aff
56+
assert s aff = liftEff <<< assertEff s =<< try aff
5757

5858
test_pure eff. TestEff eff Unit
5959
test_pure = runAssertEq "pure" 42 (pure 42)
@@ -65,16 +65,16 @@ test_bind = runAssertEq "bind" 44 do
6565
n3 ← pure (n2 + 1)
6666
pure n3
6767

68-
test_attempt eff. TestEff eff Unit
69-
test_attempt = runAssert "attempt" do
70-
n ← attempt (pure 42)
68+
test_try eff. TestEff eff Unit
69+
test_try = runAssert "try" do
70+
n ← try (pure 42)
7171
case n of
7272
Right 42 → pure true
7373
_ → pure false
7474

7575
test_throw eff. TestEff eff Unit
76-
test_throw = runAssert "attempt/throw" do
77-
n ← attempt (throwError (error "Nope."))
76+
test_throw = runAssert "try/throw" do
77+
n ← try (throwError (error "Nope."))
7878
pure (isLeft n)
7979

8080
test_liftEff eff. TestEff eff Unit
@@ -115,12 +115,12 @@ test_join_throw = assert "join/throw" do
115115
thread ← forkAff do
116116
delay (Milliseconds 10.0)
117117
throwError (error "Nope.")
118-
isLeft <$> attempt (joinThread thread)
118+
isLeft <$> try (joinThread thread)
119119

120120
test_join_throw_sync eff. TestAff eff Unit
121121
test_join_throw_sync = assert "join/throw/sync" do
122122
thread ← forkAff (throwError (error "Nope."))
123-
isLeft <$> attempt (joinThread thread)
123+
isLeft <$> try (joinThread thread)
124124

125125
test_multi_join eff. TestAff eff Unit
126126
test_multi_join = assert "join/multi" do
@@ -212,7 +212,7 @@ test_kill ∷ ∀ eff. TestAff eff Unit
212212
test_kill = assert "kill" do
213213
thread ← forkAff $ makeAff \_ → pure nonCanceler
214214
killThread (error "Nope") thread
215-
isLeft <$> attempt (joinThread thread)
215+
isLeft <$> try (joinThread thread)
216216

217217
test_kill_canceler eff. TestAff eff Unit
218218
test_kill_canceler = assert "kill/canceler" do
@@ -221,7 +221,7 @@ test_kill_canceler = assert "kill/canceler" do
221221
n ← makeAff \_ → pure (Canceler \_ → liftEff (writeRef ref 42))
222222
writeRef ref 2
223223
killThread (error "Nope") thread
224-
res ← attempt (joinThread thread)
224+
res ← try (joinThread thread)
225225
n ← readRef ref
226226
pure (n == 42 && (lmap message res) == Left "Nope")
227227

@@ -238,7 +238,7 @@ test_kill_bracket = assert "kill/bracket" do
238238
(\_ → action "b")
239239
(\_ → action "c")
240240
killThread (error "Nope") thread
241-
_ ← attempt (joinThread thread)
241+
_ ← try (joinThread thread)
242242
eq "ab" <$> readRef ref
243243

244244
test_kill_bracket_nested eff. TestAff eff Unit
@@ -260,7 +260,7 @@ test_kill_bracket_nested = assert "kill/bracket/nested" do
260260
(\s → void $ bracketAction (s <> "/release"))
261261
(\s → bracketAction (s <> "/run"))
262262
killThread (error "Nope") thread
263-
_ ← attempt (joinThread thread)
263+
_ ← try (joinThread thread)
264264
readRef ref <#> eq
265265
[ "foo/bar"
266266
, "foo/bar/run"
@@ -274,7 +274,7 @@ main ∷ TestEff () Unit
274274
main = do
275275
test_pure
276276
test_bind
277-
test_attempt
277+
test_try
278278
test_throw
279279
test_liftEff
280280

0 commit comments

Comments
 (0)