Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"scripts": {
"clean": "rimraf output && rimraf .pulp-cache",
"build": "eslint src && pulp build -- --censor-lib --strict",
"test": "pulp test"
"test": "pulp test --check-main-type Effect.Effect"
},
"devDependencies": {
"eslint": "^4.19.1",
Expand Down
36 changes: 18 additions & 18 deletions src/Data/Record.purs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import Data.Function.Uncurried (runFn2, runFn3)
import Data.Record.Unsafe (unsafeGetFn, unsafeSetFn, unsafeDeleteFn)
import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol)
import Prelude (class Eq, (&&), (==))
import Type.Row (class RowLacks, class RowToList, Cons, Nil, RLProxy(RLProxy), kind RowList)
import Type.Row (class Lacks, class Cons, class RowToList, Cons, Nil, RLProxy(RLProxy), kind RowList)

-- | Get a property for a label which is specified using a value-level proxy for
-- | a type-level string.
Expand All @@ -27,7 +27,7 @@ import Type.Row (class RowLacks, class RowToList, Cons, Nil, RLProxy(RLProxy), k
get
:: forall r r' l a
. IsSymbol l
=> RowCons l a r' r
=> Cons l a r' r
=> SProxy l
-> Record r
-> a
Expand All @@ -45,8 +45,8 @@ get l r = runFn2 unsafeGetFn (reflectSymbol l) r
set
:: forall r1 r2 r l a b
. IsSymbol l
=> RowCons l a r r1
=> RowCons l b r r2
=> Cons l a r r1
=> Cons l b r r2
=> SProxy l
-> b
-> Record r1
Expand All @@ -65,8 +65,8 @@ set l b r = runFn3 unsafeSetFn (reflectSymbol l) b r
modify
:: forall r1 r2 r l a b
. IsSymbol l
=> RowCons l a r r1
=> RowCons l b r r2
=> Cons l a r r1
=> Cons l b r r2
=> SProxy l
-> (a -> b)
-> Record r1
Expand All @@ -80,13 +80,13 @@ modify l f r = set l (f (get l r)) r
-- |
-- | ```purescript
-- | insert (SProxy :: SProxy "x")
-- | :: forall r a. RowLacks "x" r => a -> { | r } -> { x :: a | r }
-- | :: forall r a. Lacks "x" r => a -> { | r } -> { x :: a | r }
-- | ```
insert
:: forall r1 r2 l a
. IsSymbol l
=> RowLacks l r1
=> RowCons l a r1 r2
=> Lacks l r1
=> Cons l a r1 r2
=> SProxy l
-> a
-> Record r1
Expand All @@ -103,13 +103,13 @@ insert l a r = runFn3 unsafeSetFn (reflectSymbol l) a r
-- |
-- | ```purescript
-- | delete (SProxy :: SProxy "x")
-- | :: forall r a. RowLacks "x" r => { x :: a | r } -> { | r }
-- | :: forall r a. Lacks "x" r => { x :: a | r } -> { | r }
-- | ```
delete
:: forall r1 r2 l a
. IsSymbol l
=> RowLacks l r1
=> RowCons l a r1 r2
=> Lacks l r1
=> Cons l a r1 r2
=> SProxy l
-> Record r2
-> Record r1
Expand All @@ -125,15 +125,15 @@ delete l r = runFn2 unsafeDeleteFn (reflectSymbol l) r
-- |
-- | ```purescript
-- | rename (SProxy :: SProxy "x") (SProxy :: SProxy "y")
-- | :: forall a r. RowLacks "x" r => RowLacks "y" r => { x :: a | r} -> { y :: a | r}
-- | :: forall a r. Lacks "x" r => Lacks "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
=> Cons prev ty inter input
=> Lacks prev inter
=> Cons next ty inter output
=> Lacks next inter
=> SProxy prev
-> SProxy next
-> Record input
Expand All @@ -158,7 +158,7 @@ instance equalFieldsCons
::
( IsSymbol name
, Eq ty
, RowCons name ty tailRow row
, Cons name ty tailRow row
, EqualFields tail row
) => EqualFields (Cons name ty tail) row where
equalFields _ a b = get' a == get' b && equalRest a b
Expand Down
24 changes: 12 additions & 12 deletions src/Data/Record/Builder.purs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module Data.Record.Builder
import Prelude

import Data.Symbol (class IsSymbol, SProxy, reflectSymbol)
import Type.Row (class RowLacks)
import Type.Row as Row

foreign import copyRecord :: forall r1. Record r1 -> Record r1
foreign import unsafeInsert :: forall a r1 r2. String -> a -> Record r1 -> Record r2
Expand Down Expand Up @@ -43,8 +43,8 @@ derive newtype instance categoryBuilder :: Category Builder
-- | Build by inserting a new field.
insert
:: forall l a r1 r2
. RowCons l a r1 r2
=> RowLacks l r1
. Row.Cons l a r1 r2
=> Row.Lacks l r1
=> IsSymbol l
=> SProxy l
-> a
Expand All @@ -54,8 +54,8 @@ insert l a = Builder \r1 -> unsafeInsert (reflectSymbol l) a r1
-- | Build by modifying an existing field.
modify
:: forall l a b r r1 r2
. RowCons l a r r1
=> RowCons l b r r2
. Row.Cons l a r r1
=> Row.Cons l b r r2
=> IsSymbol l
=> SProxy l
-> (a -> b)
Expand All @@ -66,8 +66,8 @@ modify l f = Builder \r1 -> unsafeModify (reflectSymbol l) f r1
delete
:: forall l a r1 r2
. IsSymbol l
=> RowLacks l r1
=> RowCons l a r1 r2
=> Row.Lacks l r1
=> Row.Cons l a r1 r2
=> SProxy l
-> Builder (Record r2) (Record r1)
delete l = Builder \r2 -> unsafeDelete (reflectSymbol l) r2
Expand All @@ -76,10 +76,10 @@ delete l = Builder \r2 -> unsafeDelete (reflectSymbol l) r2
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
=> Row.Cons l1 a r2 r1
=> Row.Lacks l1 r2
=> Row.Cons l2 a r2 r3
=> Row.Lacks l2 r2
=> SProxy l1
-> SProxy l2
-> Builder (Record r1) (Record r3)
Expand All @@ -88,7 +88,7 @@ rename l1 l2 = Builder \r1 -> unsafeRename (reflectSymbol l1) (reflectSymbol l2)
-- | Build by merging existing fields from another record.
merge
:: forall r1 r2 r3
. Union r1 r2 r3
. Row.Union r1 r2 r3
=> Record r2
-> Builder (Record r1) (Record r3)
merge r2 = Builder \r1 -> unsafeMerge r1 r2
14 changes: 4 additions & 10 deletions src/Data/Record/ST.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,27 @@ function copyRecord(rec) {
return copy;
}

exports.runSTRecord = function(rec) {
return function() {
return copyRecord(rec());
};
};

exports.freezeSTRecord = function(rec) {
exports.freeze = function(rec) {
return function() {
return copyRecord(rec);
};
};

exports.thawSTRecord = function(rec) {
exports.thaw = function(rec) {
return function() {
return copyRecord(rec);
};
};

exports.unsafePeekSTRecord = function(l) {
exports.unsafePeek = function(l) {
return function(rec) {
return function() {
return rec[l];
};
};
};

exports.unsafePokeSTRecord = function(l) {
exports.unsafePoke = function(l) {
return function(a) {
return function(rec) {
return function() {
Expand Down
62 changes: 26 additions & 36 deletions src/Data/Record/ST.purs
Original file line number Diff line number Diff line change
@@ -1,71 +1,61 @@
module Data.Record.ST
( STRecord
, freezeSTRecord
, thawSTRecord
, peekSTRecord
, pokeSTRecord
, runSTRecord
, pureSTRecord
, freeze
, thaw
, peek
, poke
) where

import Prelude

import Control.Monad.Eff (Eff, runPure)
import Control.Monad.ST (ST)
import Control.Monad.ST (ST, kind Region)
import Data.Symbol (class IsSymbol, SProxy, reflectSymbol)
import Prim.Row as Row

-- | A value of type `STRecord h r` represents a mutable record with fields `r`,
-- | belonging to the state thread `h`.
-- |
-- | Create values of type `STRecord` using `thawSTRecord`.
foreign import data STRecord :: Type -> # Type -> Type
-- | Create values of type `STRecord` using `thaw`.
foreign import data STRecord :: Region -> # Type -> Type

-- | Freeze a mutable record, creating a copy.
foreign import freezeSTRecord :: forall h r eff. STRecord h r -> Eff (st :: ST h | eff) (Record r)
foreign import freeze :: forall h r. STRecord h r -> ST h (Record r)

-- | Thaw an immutable record, creating a copy.
foreign import thawSTRecord :: forall h r eff. Record r -> Eff (st :: ST h | eff) (STRecord h r)
foreign import thaw :: forall h r. Record r -> ST h (STRecord h r)

-- | Run an ST computation safely, constructing a record.
foreign import runSTRecord :: forall r eff. (forall h. Eff (st :: ST h | eff) (STRecord h r)) -> Eff eff (Record r)

-- | Run an ST computation safely, constructing a record, assuming no other
-- | types of effects.
pureSTRecord :: forall r. (forall h eff. Eff (st :: ST h | eff) (STRecord h r)) -> Record r
pureSTRecord st = runPure (runSTRecord st)

foreign import unsafePeekSTRecord
:: forall a r h eff
foreign import unsafePeek
:: forall a r h
. String
-> STRecord h r
-> Eff (st :: ST h | eff) a
-> ST h a

-- | Read the current value of a field in a mutable record, by providing a
-- | type-level representative for the label which should be read.
peekSTRecord
:: forall l h a r r1 eff
. RowCons l a r1 r
peek
:: forall l h a r r1
. Row.Cons l a r1 r
=> IsSymbol l
=> SProxy l
-> STRecord h r
-> Eff (st :: ST h | eff) a
peekSTRecord l = unsafePeekSTRecord (reflectSymbol l)
-> ST h a
peek l = unsafePeek (reflectSymbol l)

foreign import unsafePokeSTRecord
:: forall a r h eff
foreign import unsafePoke
:: forall a r h
. String
-> a
-> STRecord h r
-> Eff (st :: ST h | eff) Unit
-> ST h Unit

-- | Modify a record in place, by providing a type-level representative for the label
-- | which should be updated.
pokeSTRecord
:: forall l h a r r1 eff
. RowCons l a r1 r
poke
:: forall l h a r r1
. Row.Cons l a r1 r
=> IsSymbol l
=> SProxy l
-> a
-> STRecord h r
-> Eff (st :: ST h | eff) Unit
pokeSTRecord l = unsafePokeSTRecord (reflectSymbol l)
-> ST h Unit
poke l = unsafePoke (reflectSymbol l)
19 changes: 10 additions & 9 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ module Test.Main where

import Prelude

import Control.Monad.Eff (Eff)
import Effect (Effect)
import Data.Record (delete, equal, get, insert, modify, rename, set)
import Data.Record.Builder as Builder
import Data.Record.ST (pokeSTRecord, pureSTRecord, thawSTRecord)
import Control.Monad.ST (run) as ST
import Data.Record.ST (poke, thaw, freeze) as ST
import Data.Record.Unsafe (unsafeHas)
import Data.Symbol (SProxy(..))
import Test.Assert (ASSERT, assert')
import Test.Assert (assert')

main :: Eff (assert :: ASSERT) Unit
main :: Effect Unit
main = do
let x = SProxy :: SProxy "x"
y = SProxy :: SProxy "y"
Expand All @@ -37,11 +38,11 @@ main = do
assert' "unsafeHas2" $
not $ unsafeHas "b" { a: 42 }

let stTest1 = pureSTRecord do
rec <- thawSTRecord { x: 41, y: "" }
pokeSTRecord x 42 rec
pokeSTRecord y "testing" rec
pure rec
let stTest1 = ST.run do
rec <- ST.thaw { x: 41, y: "" }
ST.poke x 42 rec
ST.poke y "testing" rec
ST.freeze rec

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