Skip to content

Commit b337e06

Browse files
justinwoopaf31
authored andcommitted
add rename and Builder.rename (#18)
1 parent 94c0538 commit b337e06

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

src/Data/Record.purs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module Data.Record
44
, modify
55
, insert
66
, delete
7+
, rename
78
, equal
89
, class EqualFields
910
, equalFields
@@ -114,6 +115,32 @@ delete
114115
-> Record r1
115116
delete l r = runFn2 unsafeDeleteFn (reflectSymbol l) r
116117

118+
-- | Rename a property for a label which is specified using a value-level proxy for
119+
-- | a type-level string.
120+
-- |
121+
-- | Note that the type of the resulting row must _lack_ the specified property.
122+
-- | Since duplicate labels are allowed, this is checked with a type class constraint.
123+
-- |
124+
-- | For example:
125+
-- |
126+
-- | ```purescript
127+
-- | rename (SProxy :: SProxy "x") (SProxy :: SProxy "y")
128+
-- | :: forall a r. RowLacks "x" r => RowLacks "y" r => { x :: a | r} -> { y :: a | r}
129+
-- | ```
130+
rename :: forall prev next ty input inter output
131+
. IsSymbol prev
132+
=> IsSymbol next
133+
=> RowCons prev ty inter input
134+
=> RowLacks prev inter
135+
=> RowCons next ty inter output
136+
=> RowLacks next inter
137+
=> SProxy prev
138+
-> SProxy next
139+
-> Record input
140+
-> Record output
141+
rename prev next record =
142+
insert next (get prev record) (delete prev record :: Record inter)
143+
117144
-- | Check two records of the same type for equality.
118145
equal
119146
:: forall r rs

src/Data/Record/Builder.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ exports.unsafeDelete = function(l) {
2626
};
2727
};
2828

29+
exports.unsafeRename = function(l1) {
30+
return function (l2) {
31+
return function (rec) {
32+
rec[l2] = rec[l1];
33+
delete rec[l1];
34+
return rec;
35+
};
36+
};
37+
};
38+
2939
exports.unsafeMerge = function(r1) {
3040
return function(r2) {
3141
var copy = {};

src/Data/Record/Builder.purs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Data.Record.Builder
33
, build
44
, insert
55
, delete
6+
, rename
67
, merge
78
) where
89

@@ -14,6 +15,7 @@ import Type.Row (class RowLacks)
1415
foreign import copyRecord :: forall r1. Record r1 -> Record r1
1516
foreign import unsafeInsert :: forall a r1 r2. String -> a -> Record r1 -> Record r2
1617
foreign import unsafeDelete :: forall r1 r2. String -> Record r1 -> Record r2
18+
foreign import unsafeRename :: forall r1 r2. String -> String -> Record r1 -> Record r2
1719
foreign import unsafeMerge :: forall r1 r2 r3. Record r1 -> Record r2 -> Record r3
1820

1921
-- | A `Builder` can be used to `build` a record by incrementally adding
@@ -57,6 +59,19 @@ delete
5759
-> Builder (Record r2) (Record r1)
5860
delete l = Builder \r2 -> unsafeDelete (reflectSymbol l) r2
5961

62+
-- | Build by renaming an existing field.
63+
rename :: forall l1 l2 a r1 r2 r3
64+
. IsSymbol l1
65+
=> IsSymbol l2
66+
=> RowCons l1 a r2 r1
67+
=> RowLacks l1 r2
68+
=> RowCons l2 a r2 r3
69+
=> RowLacks l2 r2
70+
=> SProxy l1
71+
-> SProxy l2
72+
-> Builder (Record r1) (Record r3)
73+
rename l1 l2 = Builder \r1 -> unsafeRename (reflectSymbol l1) (reflectSymbol l2) r1
74+
6075
-- | Build by merging existing fields from another record.
6176
merge
6277
:: forall r1 r2 r3

test/Main.purs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module Test.Main where
33
import Prelude
44

55
import Control.Monad.Eff (Eff)
6-
import Data.Record (delete, get, insert, modify, set, equal)
6+
import Data.Record (delete, equal, get, insert, modify, rename, set)
77
import Data.Record.Builder as Builder
88
import Data.Record.ST (pokeSTRecord, pureSTRecord, thawSTRecord)
99
import Data.Record.Unsafe (unsafeHas)
@@ -14,6 +14,7 @@ main :: Eff (assert :: ASSERT) Unit
1414
main = do
1515
let x = SProxy :: SProxy "x"
1616
y = SProxy :: SProxy "y"
17+
z = SProxy :: SProxy "z"
1718

1819
assert' "insert, get" $
1920
get x (insert x 42 {}) == 42
@@ -25,6 +26,8 @@ main = do
2526
get x (modify x (_ + 1) (set x 0 { x: 42 })) == 1
2627
assert' "delete, get" $
2728
get x (delete y { x: 42, y: 1337 }) == 42
29+
assert' "rename" $
30+
get y (rename x y { x: 42 }) == 42
2831
assert' "equal" $
2932
equal { a: 1, b: "b", c: true } { a: 1, b: "b", c: true }
3033
assert' "equal2" $
@@ -42,10 +45,11 @@ main = do
4245

4346
assert' "pokeSTRecord" $
4447
stTest1.x == 42 && stTest1.y == "testing"
45-
48+
4649
let testBuilder = Builder.build (Builder.insert x 42
4750
>>> Builder.merge { y: true, z: "testing" }
48-
>>> Builder.delete y) {}
51+
>>> Builder.delete y
52+
>>> Builder.rename z y) {}
4953

5054
assert' "Data.Record.Builder" $
51-
testBuilder.x == 42 && testBuilder.z == "testing"
55+
testBuilder.x == 42 && testBuilder.y == "testing"

0 commit comments

Comments
 (0)