Skip to content

Commit 67ad0d2

Browse files
committed
Add lazy thread map
1 parent 7d71cba commit 67ad0d2

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

src/Control/Monad/Aff.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,32 @@ exports.bracket = function (acquire) {
9090
};
9191
};
9292

93+
exports.mapThread = function () {
94+
var EMPTY = {};
95+
96+
return function (f) {
97+
return function (thread) {
98+
var value = EMPTY;
99+
100+
function force() {
101+
if (value === EMPTY) {
102+
return new Aff(BIND, thread.join, function (result) {
103+
value = new Aff(PURE, f(result));
104+
return value;
105+
});
106+
} else {
107+
return value;
108+
}
109+
}
110+
111+
return {
112+
kill: thread.kill,
113+
join: new Aff(BIND, new Aff(PURE, void 0), force)
114+
};
115+
};
116+
};
117+
}();
118+
93119
exports._delay = function () {
94120
var setDelay = function (n, k) {
95121
if (n === 0 && typeof setImmediate !== "undefined") {

src/Control/Monad/Aff.purs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module Control.Monad.Aff
1515
, atomically
1616
, killThread
1717
, joinThread
18+
, module Exports
1819
) where
1920

2021
import Prelude
@@ -28,6 +29,7 @@ import Control.Monad.Eff.Ref (newRef, readRef, writeRef)
2829
import Control.Monad.Eff.Ref.Unsafe (unsafeRunRef)
2930
import Control.Monad.Eff.Unsafe (unsafeCoerceEff)
3031
import Control.Monad.Error.Class (class MonadError, class MonadThrow, throwError, catchError, try)
32+
import Control.Monad.Error.Class (try) as Exports
3133
import Control.Monad.Rec.Class (class MonadRec, Step(..))
3234
import Control.MonadPlus (class MonadPlus)
3335
import Control.MonadZero (class MonadZero)
@@ -188,7 +190,7 @@ newtype Thread eff a = Thread
188190
}
189191

190192
instance functorThreadFunctor (Thread eff) where
191-
map f (Thread { kill, join }) = Thread { kill, join: f <$> join }
193+
map = mapThread
192194

193195
killThread eff a. Error Thread eff a Aff eff Unit
194196
killThread e (Thread t) = t.kill e
@@ -240,6 +242,7 @@ foreign import _delay ∷ ∀ a eff. Fn.Fn2 (Unit → Either a Unit) Number (Aff
240242
foreign import _liftEff eff a. Eff eff a Aff eff a
241243
foreign import bracket eff a b. Aff eff a (a Aff eff Unit) (a Aff eff b) Aff eff b
242244
foreign import makeAff eff a. ((Either Error a Eff eff Unit) Eff eff (Canceler eff)) Aff eff a
245+
foreign import mapThread eff a b. (a b) Thread eff a Thread eff b
243246

244247
foreign import _launchAff
245248
eff a

test/Test/Main.purs

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

33
import Prelude
44
import Control.Alt ((<|>))
5-
import Control.Monad.Aff (Aff, Canceler(..), ASYNC, nonCanceler, runAff, launchAff, makeAff, try, bracket, delay, forkAff, joinThread, killThread)
6-
import Control.Monad.Eff (Eff)
5+
import Control.Monad.Aff (Aff, Canceler(..), nonCanceler, runAff, launchAff, makeAff, try, bracket, delay, forkAff, joinThread, killThread)
6+
import Control.Monad.Eff (Eff, runPure)
77
import Control.Monad.Eff.Class (class MonadEff, liftEff)
88
import Control.Monad.Eff.Console (CONSOLE)
99
import Control.Monad.Eff.Console as Console
1010
import Control.Monad.Eff.Exception (Error, EXCEPTION, throwException, error, message)
1111
import Control.Monad.Eff.Ref (REF, Ref)
1212
import Control.Monad.Eff.Ref as Ref
13+
import Control.Monad.Eff.Ref.Unsafe (unsafeRunRef)
1314
import Control.Monad.Error.Class (throwError)
1415
import Control.Parallel (parallel, sequential)
1516
import Data.Bifunctor (lmap)
@@ -21,7 +22,7 @@ import Data.Time.Duration (Milliseconds(..))
2122
import Test.Assert (assert', ASSERT)
2223

2324
type TestEffects eff = (assert ASSERT, console CONSOLE, ref REF, exception EXCEPTION | eff)
24-
type TestEff eff = Eff (TestEffects (async ASYNC | eff))
25+
type TestEff eff = Eff (TestEffects eff)
2526
type TestAff eff = Aff (TestEffects eff)
2627

2728
newRef m eff a. MonadEff (ref REF | eff) m a m (Ref a)
@@ -346,6 +347,23 @@ test_kill_parallel_alt = assert "kill/parallel/alt" do
346347
_ ← try $ joinThread t2
347348
eq "killedfookilledbardone" <$> readRef ref
348349

350+
test_mapThread eff. TestAff eff Unit
351+
test_mapThread = assert "mapThread" do
352+
ref ← newRef 0
353+
let
354+
mapFn a = runPure do
355+
unsafeRunRef $ Ref.modifyRef ref (_ + 1)
356+
pure (a + 1)
357+
t1 ← forkAff do
358+
delay (Milliseconds 10.0)
359+
pure 10
360+
let
361+
t2 = mapFn <$> t1
362+
a ← joinThread t2
363+
b ← joinThread t2
364+
n ← readRef ref
365+
pure (a == 11 && b == 11 && n == 1)
366+
349367
main TestEff () Unit
350368
main = do
351369
test_pure
@@ -372,3 +390,4 @@ main = do
372390
test_kill_parallel
373391
test_parallel_alt
374392
test_kill_parallel_alt
393+
test_mapThread

0 commit comments

Comments
 (0)