Skip to content

Commit

Permalink
add rename and Builder.rename (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinwoo authored and paf31 committed Nov 15, 2017
1 parent 94c0538 commit b337e06
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 4 deletions.
27 changes: 27 additions & 0 deletions src/Data/Record.purs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Data.Record
, modify
, insert
, delete
, rename
, equal
, class EqualFields
, equalFields
Expand Down Expand Up @@ -114,6 +115,32 @@ delete
-> Record r1
delete l r = runFn2 unsafeDeleteFn (reflectSymbol l) r

-- | Rename a property for a label which is specified using a value-level proxy for
-- | a type-level string.
-- |
-- | Note that the type of the resulting row must _lack_ the specified property.
-- | Since duplicate labels are allowed, this is checked with a type class constraint.
-- |
-- | For example:
-- |
-- | ```purescript
-- | rename (SProxy :: SProxy "x") (SProxy :: SProxy "y")
-- | :: forall a r. RowLacks "x" r => RowLacks "y" r => { x :: a | r} -> { y :: a | r}
-- | ```
rename :: forall prev next ty input inter output
. IsSymbol prev
=> IsSymbol next
=> RowCons prev ty inter input
=> RowLacks prev inter
=> RowCons next ty inter output
=> RowLacks next inter
=> SProxy prev
-> SProxy next
-> Record input
-> Record output
rename prev next record =
insert next (get prev record) (delete prev record :: Record inter)

-- | Check two records of the same type for equality.
equal
:: forall r rs
Expand Down
10 changes: 10 additions & 0 deletions src/Data/Record/Builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ exports.unsafeDelete = function(l) {
};
};

exports.unsafeRename = function(l1) {
return function (l2) {
return function (rec) {
rec[l2] = rec[l1];
delete rec[l1];
return rec;
};
};
};

exports.unsafeMerge = function(r1) {
return function(r2) {
var copy = {};
Expand Down
15 changes: 15 additions & 0 deletions src/Data/Record/Builder.purs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Data.Record.Builder
, build
, insert
, delete
, rename
, merge
) where

Expand All @@ -14,6 +15,7 @@ import Type.Row (class RowLacks)
foreign import copyRecord :: forall r1. Record r1 -> Record r1
foreign import unsafeInsert :: forall a r1 r2. String -> a -> Record r1 -> Record r2
foreign import unsafeDelete :: forall r1 r2. String -> Record r1 -> Record r2
foreign import unsafeRename :: forall r1 r2. String -> String -> Record r1 -> Record r2
foreign import unsafeMerge :: forall r1 r2 r3. Record r1 -> Record r2 -> Record r3

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

-- | Build by renaming an existing field.
rename :: forall l1 l2 a r1 r2 r3
. IsSymbol l1
=> IsSymbol l2
=> RowCons l1 a r2 r1
=> RowLacks l1 r2
=> RowCons l2 a r2 r3
=> RowLacks l2 r2
=> SProxy l1
-> SProxy l2
-> Builder (Record r1) (Record r3)
rename l1 l2 = Builder \r1 -> unsafeRename (reflectSymbol l1) (reflectSymbol l2) r1

-- | Build by merging existing fields from another record.
merge
:: forall r1 r2 r3
Expand Down
12 changes: 8 additions & 4 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Test.Main where
import Prelude

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

assert' "insert, get" $
get x (insert x 42 {}) == 42
Expand All @@ -25,6 +26,8 @@ main = do
get x (modify x (_ + 1) (set x 0 { x: 42 })) == 1
assert' "delete, get" $
get x (delete y { x: 42, y: 1337 }) == 42
assert' "rename" $
get y (rename x y { x: 42 }) == 42
assert' "equal" $
equal { a: 1, b: "b", c: true } { a: 1, b: "b", c: true }
assert' "equal2" $
Expand All @@ -42,10 +45,11 @@ main = do

assert' "pokeSTRecord" $
stTest1.x == 42 && stTest1.y == "testing"

let testBuilder = Builder.build (Builder.insert x 42
>>> Builder.merge { y: true, z: "testing" }
>>> Builder.delete y) {}
>>> Builder.delete y
>>> Builder.rename z y) {}

assert' "Data.Record.Builder" $
testBuilder.x == 42 && testBuilder.z == "testing"
testBuilder.x == 42 && testBuilder.y == "testing"

0 comments on commit b337e06

Please sign in to comment.