diff --git a/src/Record.purs b/src/Record.purs index 11154ca..2491b69 100644 --- a/src/Record.purs +++ b/src/Record.purs @@ -31,16 +31,15 @@ import Unsafe.Coerce (unsafeCoerce) -- | For example: -- | -- | ```purescript --- | get (Proxy :: Proxy "x") :: forall r a. { x :: a | r } -> a +-- | get @"x" :: forall r a. { x :: a | r } -> a -- | ``` get - :: forall r r' l a + :: forall r r' @l a . IsSymbol l => Cons l a r' r - => Proxy l - -> Record r + => Record r -> a -get l r = unsafeGet (reflectSymbol l) r +get r = unsafeGet (reflectSymbol (Proxy :: _ l)) r -- | Set a property for a label which is specified using a value-level proxy for -- | a type-level string. @@ -48,19 +47,18 @@ get l r = unsafeGet (reflectSymbol l) r -- | For example: -- | -- | ```purescript --- | set (Proxy :: Proxy "x") +-- | set @"x" -- | :: forall r a b. a -> { x :: b | r } -> { x :: a | r } -- | ``` set - :: forall r1 r2 r l a b + :: forall r1 r2 r @l a b . IsSymbol l => Cons l a r r1 => Cons l b r r2 - => Proxy l - -> b + => b -> Record r1 -> Record r2 -set l b r = unsafeSet (reflectSymbol l) b r +set b r = unsafeSet (reflectSymbol (Proxy :: _ l)) b r -- | Modify a property for a label which is specified using a value-level proxy for -- | a type-level string. @@ -68,19 +66,18 @@ set l b r = unsafeSet (reflectSymbol l) b r -- | For example: -- | -- | ```purescript --- | modify (Proxy :: Proxy "x") +-- | modify @"x" -- | :: forall r a b. (a -> b) -> { x :: a | r } -> { x :: b | r } -- | ``` modify - :: forall r1 r2 r l a b + :: forall r1 r2 r @l a b . IsSymbol l => Cons l a r r1 => Cons l b r r2 - => Proxy l - -> (a -> b) + => (a -> b) -> Record r1 -> Record r2 -modify l f r = set l (f (get l r)) r +modify f r = set @l (f (get @l r)) r -- | Insert a new property for a label which is specified using a value-level proxy for -- | a type-level string. @@ -88,19 +85,18 @@ modify l f r = set l (f (get l r)) r -- | For example: -- | -- | ```purescript --- | insert (Proxy :: Proxy "x") +-- | insert @"x" -- | :: forall r a. Lacks "x" r => a -> { | r } -> { x :: a | r } -- | ``` insert - :: forall r1 r2 l a + :: forall r1 r2 @l a . IsSymbol l => Lacks l r1 => Cons l a r1 r2 - => Proxy l - -> a + => a -> Record r1 -> Record r2 -insert l a r = unsafeSet (reflectSymbol l) a r +insert a r = unsafeSet (reflectSymbol (Proxy :: _ l)) a r -- | Delete a property for a label which is specified using a value-level proxy for -- | a type-level string. @@ -111,18 +107,17 @@ insert l a r = unsafeSet (reflectSymbol l) a r -- | For example: -- | -- | ```purescript --- | delete (Proxy :: Proxy "x") +-- | delete @"x" -- | :: forall r a. Lacks "x" r => { x :: a | r } -> { | r } -- | ``` delete - :: forall r1 r2 l a + :: forall r1 r2 @l a . IsSymbol l => Lacks l r1 => Cons l a r1 r2 - => Proxy l - -> Record r2 + => Record r2 -> Record r1 -delete l r = unsafeDelete (reflectSymbol l) r +delete r = unsafeDelete (reflectSymbol (Proxy :: _ l)) r -- | Rename a property for a label which is specified using a value-level proxy for -- | a type-level string. @@ -133,22 +128,21 @@ delete l r = unsafeDelete (reflectSymbol l) r -- | For example: -- | -- | ```purescript --- | rename (Proxy :: Proxy "x") (Proxy :: Proxy "y") +-- | rename @"x" @"y" -- | :: forall a r. Lacks "x" r => Lacks "y" r => { x :: a | r} -> { y :: a | r} -- | ``` -rename :: forall prev next ty input inter output +rename + :: forall @prev @next ty input inter output . IsSymbol prev => IsSymbol next => Cons prev ty inter input => Lacks prev inter => Cons next ty inter output => Lacks next inter - => Proxy prev - -> Proxy next - -> Record input + => Record input -> Record output -rename prev next record = - insert next (get prev record) (delete prev record :: Record inter) +rename record = + insert @next (get @prev record) (delete @prev record :: Record inter) -- | Merges two records with the first record's labels taking precedence in the -- | case of overlaps. @@ -221,22 +215,22 @@ equal => Record r -> Record r -> Boolean -equal a b = equalFields (Proxy :: Proxy rs) a b +equal a b = equalFields @rs a b class EqualFields (rs :: RowList Type) (row :: Row Type) | rs -> row where - equalFields :: Proxy rs -> Record row -> Record row -> Boolean + equalFields :: Record row -> Record row -> Boolean -instance equalFieldsCons - :: +instance equalFieldsCons :: ( IsSymbol name , Eq ty , 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 + ) => + EqualFields (Cons name ty tail) row where + equalFields a b = get' a == get' b && equalRest a b where - get' = get (Proxy :: Proxy name) - equalRest = equalFields (Proxy :: Proxy tail) + get' = get @name + equalRest = equalFields @tail instance equalFieldsNil :: EqualFields Nil row where - equalFields _ _ _ = true + equalFields _ _ = true diff --git a/src/Record/Builder.purs b/src/Record/Builder.purs index acc204f..c983450 100644 --- a/src/Record/Builder.purs +++ b/src/Record/Builder.purs @@ -20,7 +20,7 @@ import Data.Function.Uncurried (runFn2) import Data.Symbol (class IsSymbol, reflectSymbol) import Prim.Row as Row import Record.Unsafe.Union (unsafeUnionFn) -import Type.Proxy (Proxy) +import Type.Proxy (Proxy(..)) import Unsafe.Coerce (unsafeCoerce) foreign import copyRecord :: forall r1. Record r1 -> Record r1 @@ -41,12 +41,12 @@ foreign import unsafeRename :: forall r1 r2. String -> String -> Record r1 -> Re -- | For example: -- | -- | ```purescript --- | build (insert x 42 >>> insert y "testing") {} :: { x :: Int, y :: String } +-- | build (insert @"x" 42 >>> insert @"y" "testing") {} :: { x :: Int, y :: String } -- | ``` newtype Builder a b = Builder (a -> b) -- | Build a record, starting from some other record. -build :: forall r1 r2. Builder (Record r1) (Record r2) -> Record r1 -> Record r2 +build :: forall @r1 r2. Builder (Record r1) (Record r2) -> Record r1 -> Record r2 build (Builder b) r1 = b (copyRecord r1) -- | Build a record from scratch. @@ -62,48 +62,44 @@ derive newtype instance categoryBuilder :: Category Builder -- | Build by inserting a new field. insert - :: forall l a r1 r2 + :: forall @l a r1 r2 . Row.Cons l a r1 r2 => Row.Lacks l r1 => IsSymbol l - => Proxy l - -> a + => a -> Builder (Record r1) (Record r2) -insert l a = Builder \r1 -> unsafeInsert (reflectSymbol l) a r1 +insert a = Builder \r1 -> unsafeInsert (reflectSymbol (Proxy :: _ l)) a r1 -- | Build by modifying an existing field. modify - :: forall l a b r r1 r2 + :: forall @l a b r r1 r2 . Row.Cons l a r r1 => Row.Cons l b r r2 => IsSymbol l - => Proxy l - -> (a -> b) + => (a -> b) -> Builder (Record r1) (Record r2) -modify l f = Builder \r1 -> unsafeModify (reflectSymbol l) f r1 +modify f = Builder \r1 -> unsafeModify (reflectSymbol (Proxy :: _ l)) f r1 -- | Build by deleting an existing field. delete - :: forall l a r1 r2 + :: forall @l a r1 r2 . IsSymbol l - => Row.Lacks l r1 - => Row.Cons l a r1 r2 - => Proxy l - -> Builder (Record r2) (Record r1) -delete l = Builder \r2 -> unsafeDelete (reflectSymbol l) r2 + => Row.Lacks l r1 + => Row.Cons l a r1 r2 + => Builder (Record r2) (Record r1) +delete = Builder \r2 -> unsafeDelete (reflectSymbol (Proxy :: _ l)) r2 -- | Build by renaming an existing field. -rename :: forall l1 l2 a r1 r2 r3 +rename + :: forall @l1 @l2 a r1 r2 r3 . IsSymbol l1 => IsSymbol l2 => Row.Cons l1 a r2 r1 => Row.Lacks l1 r2 => Row.Cons l2 a r2 r3 => Row.Lacks l2 r2 - => Proxy l1 - -> Proxy l2 - -> Builder (Record r1) (Record r3) -rename l1 l2 = Builder \r1 -> unsafeRename (reflectSymbol l1) (reflectSymbol l2) r1 + => Builder (Record r1) (Record r3) +rename = Builder \r1 -> unsafeRename (reflectSymbol (Proxy :: _ l1)) (reflectSymbol (Proxy :: _ l2)) r1 -- | Build by merging existing fields from another record, taking precedence -- | in the case of overlaps. diff --git a/test/Examples.purs b/test/Examples.purs index 42b7b9d..84b0374 100644 --- a/test/Examples.purs +++ b/test/Examples.purs @@ -10,7 +10,7 @@ y_ = Proxy :: Proxy "y" z_ = Proxy :: Proxy "z" gotX :: Int -gotX = Record.get x_ { x: 1 } +gotX = Record.get @"x" { x: 1 } insertedX :: { x :: Int } insertedX = Record.insert x_ 1 {} @@ -19,10 +19,10 @@ deletedX :: {} deletedX = Record.delete x_ { x: 1 } setX1 :: { x :: Int } -setX1 = Record.set x_ 1 { x: 0 } +setX1 = Record.set @"x" 1 { x: 0 } setX2 :: { x :: Unit } -setX2 = Record.set x_ unit { x: 0 } +setX2 = Record.set @"x" unit { x: 0 } modifyX :: { x :: Int } modifyX = Record.modify x_ (\value -> value + 1) { x: 0 } diff --git a/test/Main.purs b/test/Main.purs index 124f3cd..c97ed9d 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -7,62 +7,76 @@ import Record (delete, equal, get, insert, merge, modify, rename, set) import Record.Builder as Builder import Record.Unsafe (unsafeHas) import Test.Assert (assert') -import Type.Proxy (Proxy(..)) main :: Effect Unit main = do - let x = Proxy :: Proxy "x" - y = Proxy :: Proxy "y" - z = Proxy :: Proxy "z" - assert' "insert, get" $ - get x (insert x 42 {}) == 42 + get @"x" (insert @"x" 42 {}) == 42 assert' "insert, modify, get" $ - get x (modify x (_ + 1) (insert x 42 {})) == 43 + get @"x" (modify @"x" (_ + 1) (insert @"x" 42 {})) == 43 assert' "set, get" $ - get x (set x 0 { x: 42 }) == 0 + get @"x" (set @"x" 0 { x: 42 }) == 0 assert' "set, modify, get" $ - get x (modify x (_ + 1) (set x 0 { x: 42 })) == 1 + get @"x" (modify @"x" (_ + 1) (set @"x" 0 { x: 42 })) == 1 assert' "delete, get" $ - get x (delete y { x: 42, y: 1337 }) == 42 + get @"x" (delete @"y" { x: 42, y: 1337 }) == 42 assert' "rename" $ - get y (rename x y { x: 42 }) == 42 + 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" $ - not $ equal { a: 1, b: "b", c: true } { a: 1, b: "b", c: false } + assert' "equal2" + $ not + $ equal { a: 1, b: "b", c: true } { a: 1, b: "b", c: false } assert' "merge" $ equal { x: 1, y: "y" } (merge { y: "y" } { x: 1, y: 2 }) assert' "unsafeHas1" $ unsafeHas "a" { a: 42 } - assert' "unsafeHas2" $ - not $ unsafeHas "b" { a: 42 } + assert' "unsafeHas2" + $ not + $ unsafeHas "b" { a: 42 } - let testBuilder = Builder.build (Builder.insert x 42 - >>> Builder.merge { y: true, z: "testing" } - >>> Builder.delete y - >>> Builder.modify x show - >>> Builder.rename z y) {} + let + testBuilder = + Builder.build + ( Builder.insert @"x" 42 + >>> Builder.merge { y: true, z: "testing" } + >>> Builder.delete @"y" + >>> Builder.modify @"x" show + >>> Builder.rename @"z" @"y" + ) + {} assert' "Record.Builder" $ testBuilder.x == "42" && testBuilder.y == "testing" assert' "Record.Builder.merge" $ - let { x, y, z } = Builder.build (Builder.merge { x: 1, y: "y" }) { y: 2, z: true } + let + { x, y, z } = + Builder.build (Builder.merge { x: 1, y: "y" }) { y: 2, z: true } :: { x :: Int, y :: String, z :: Boolean } - in x == 1 && y == "y" && z + in + x == 1 && y == "y" && z assert' "Record.Builder.union" $ - let { x, y, z } = Builder.build (Builder.union { x: 1, y: "y" }) { y: 2, z: true } + let + { x, y, z } = + Builder.build (Builder.union { x: 1, y: "y" }) { y: 2, z: true } :: { x :: Int, y :: String, y :: Int, z :: Boolean } - in x == 1 && y == "y" && z + in + x == 1 && y == "y" && z assert' "Record.Builder.flip merge" $ - let { x, y, z } = Builder.build (Builder.flip Builder.merge { x: 1, y: "y" }) { y: 2, z: true } + let + { x, y, z } = + Builder.build (Builder.flip Builder.merge { x: 1, y: "y" }) { y: 2, z: true } :: { x :: Int, y :: Int, z :: Boolean } - in x == 1 && y == 2 && z + in + x == 1 && y == 2 && z assert' "Record.Builder.flip union" $ - let { x, y, z } = Builder.build (Builder.flip Builder.union { x: 1, y: "y" }) { y: 2, z: true } + let + { x, y, z } = + Builder.build (Builder.flip Builder.union { x: 1, y: "y" }) { y: 2, z: true } :: { x :: Int, y :: Int, y :: String, z :: Boolean } - in x == 1 && y == 2 && z + in + x == 1 && y == 2 && z