Skip to content

Commit 1a1b766

Browse files
authored
Allow the construction of self-referential Refs (#21)
* Allow the construction of self-referential `Ref`s * Restore FFI version of 'new' * Change name of `self` to `newSelf` * Use 'newWithSelf' name
1 parent 3575ad9 commit 1a1b766

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

src/Effect/Ref.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ exports.new = function (val) {
66
};
77
};
88

9+
exports.newWithSelf = function (f) {
10+
return function () {
11+
var ref = { value: null };
12+
ref.value = f(ref);
13+
return ref;
14+
};
15+
};
16+
917
exports.read = function (ref) {
1018
return function () {
1119
return ref.value;

src/Effect/Ref.purs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
module Effect.Ref
2323
( Ref
2424
, new
25+
, newWithSelf
2526
, read
2627
, modify'
2728
, modify
@@ -42,6 +43,10 @@ type role Ref representational
4243
-- | Create a new mutable reference containing the specified value.
4344
foreign import new :: forall s. s -> Effect (Ref s)
4445

46+
-- | Create a new mutable reference containing a value that can refer to the
47+
-- | `Ref` being created.
48+
foreign import newWithSelf :: forall s. (Ref s -> s) -> Effect (Ref s)
49+
4550
-- | Read the current value of a mutable reference.
4651
foreign import read :: forall s. Ref s -> Effect s
4752

test/Main.purs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,27 @@ main = do
2828
-- now it is 2 when we read out the value
2929
curr3 <- Ref.read ref
3030
assertEqual { actual: curr3, expected: 2 }
31+
32+
selfRef
33+
34+
newtype RefBox = RefBox { ref :: Ref.Ref RefBox, value :: Int }
35+
36+
selfRef :: Effect Unit
37+
selfRef = do
38+
-- Create a self-referential `Ref`
39+
ref <- Ref.newWithSelf \ref -> RefBox { ref, value: 0 }
40+
41+
-- Grab the `Ref` from within the `Ref`
42+
ref' <- Ref.read ref <#> \(RefBox r) -> r.ref
43+
44+
-- Modify the `ref` and check that value in `ref'` changes
45+
Ref.modify_ (\(RefBox r) -> RefBox (r { value = 1 })) ref
46+
assertEqual
47+
<<< { expected: 1, actual: _ }
48+
=<< (Ref.read ref' <#> \(RefBox { value }) -> value)
49+
50+
-- Modify the `ref'` and check that value in `ref` changes
51+
Ref.modify_ (\(RefBox r) -> RefBox (r { value = 2 })) ref'
52+
assertEqual
53+
<<< { expected: 2, actual: _ }
54+
=<< (Ref.read ref <#> \(RefBox { value }) -> value)

0 commit comments

Comments
 (0)