From 3326f477dc74752bf1ef0eb64d173b4b5e88e748 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Sat, 10 Feb 2018 20:13:33 -0800 Subject: [PATCH] ST.modify addresses https://github.com/purescript/purescript-record/issues/31 --- src/Data/Record/ST.js | 10 ++++++++++ src/Data/Record/ST.purs | 21 +++++++++++++++++++++ test/Main.purs | 6 ++++++ 3 files changed, 37 insertions(+) diff --git a/src/Data/Record/ST.js b/src/Data/Record/ST.js index 12b97c4..9c3bf8a 100644 --- a/src/Data/Record/ST.js +++ b/src/Data/Record/ST.js @@ -45,3 +45,13 @@ exports.unsafePokeSTRecord = function(l) { }; }; }; + +exports.unsafeModify = function(l) { + return function(f) { + return function(rec) { + return function() { + rec[l] = f(rec[l]); + }; + }; + }; +}; diff --git a/src/Data/Record/ST.purs b/src/Data/Record/ST.purs index 671752f..f850c27 100644 --- a/src/Data/Record/ST.purs +++ b/src/Data/Record/ST.purs @@ -4,6 +4,7 @@ module Data.Record.ST , thawSTRecord , peekSTRecord , pokeSTRecord + , modify , runSTRecord , pureSTRecord ) where @@ -69,3 +70,23 @@ pokeSTRecord -> STRecord h r -> Eff (st :: ST h | eff) Unit pokeSTRecord l = unsafePokeSTRecord (reflectSymbol l) + +foreign import unsafeModify + :: forall a r h eff + . String + -> (a -> a) + -> STRecord h r + -> Eff (st :: ST h | eff) Unit + +-- | Modify a record in place, +-- | by providing a type-level representative for the label to update +-- | and a function to update it. +modify + :: forall l h a r r1 eff + . RowCons l a r1 r + => IsSymbol l + => SProxy l + -> (a -> a) + -> STRecord h r + -> Eff (st :: ST h | eff) Unit +modify l = unsafeModify (reflectSymbol l) diff --git a/test/Main.purs b/test/Main.purs index 1c2a34b..263436b 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -6,6 +6,7 @@ import Control.Monad.Eff (Eff) 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.ST as ST import Data.Record.Unsafe (unsafeHas) import Data.Symbol (SProxy(..)) import Test.Assert (ASSERT, assert') @@ -42,9 +43,14 @@ main = do pokeSTRecord x 42 rec pokeSTRecord y "testing" rec pure rec + stTest2 = pureSTRecord do + rec <- thawSTRecord { x: 41 } + ST.modify x (_ + 1) rec + pure rec assert' "pokeSTRecord" $ stTest1.x == 42 && stTest1.y == "testing" + assert' "ST.modify" $ stTest2.x == 42 let testBuilder = Builder.build (Builder.insert x 42 >>> Builder.merge { y: true, z: "testing" }