From 850360dbfa1bf765a19b3ec207a706622fa47ac7 Mon Sep 17 00:00:00 2001 From: Athan Clark Date: Fri, 1 Sep 2017 19:50:18 -0600 Subject: [PATCH 1/2] classes from @doolse's purescript-records: https://github.com/doolse/purescript-records/pull/2#issuecomment-326206312 --- src/Data/Record/Class.js | 8 ++++++ src/Data/Record/Class.purs | 51 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/Data/Record/Class.js create mode 100644 src/Data/Record/Class.purs diff --git a/src/Data/Record/Class.js b/src/Data/Record/Class.js new file mode 100644 index 0000000..b172c93 --- /dev/null +++ b/src/Data/Record/Class.js @@ -0,0 +1,8 @@ +"use strict"; + +exports.unsafeMerge = function (l) { + return function (r) { + var o = {}; + return Object.assign(o, l, r); + }; +}; diff --git a/src/Data/Record/Class.purs b/src/Data/Record/Class.purs new file mode 100644 index 0000000..1eb5890 --- /dev/null +++ b/src/Data/Record/Class.purs @@ -0,0 +1,51 @@ +module Data.Record.Class ( + class Subrow, + class RecordMerge, + class IntersectRow, + merge, + unionMerge +) where + +-- | Proof that row `r` is a subset of row `s` +class Subrow (r :: # Type) (s :: # Type) +instance srInst :: Union r t s => Subrow r s + +-- | Proof of row `i` being the intersection of rows `ri` and `si`, +-- | `r` is `i` subtracted from `ri` and +-- | `s` is `i` subtracted from `si` +class IntersectRow (ri :: # Type) (si :: # Type) (i :: # Type) (r :: # Type) (s :: # Type) +instance irInst :: (Union r i ri, Union i s si) => IntersectRow ri si i r s + +class RecordMerge (o :: # Type) (mr :: # Type) (mo :: # Type) +instance rmInst :: (IntersectRow mo mr m o r, Subrow r o) => RecordMerge o mr mo + + +-- | Merge any two records together unsafely. +-- | Fields common between the two will result in the value from r2 being kept +foreign import unsafeMerge + :: forall r1 r2 r3 + . Record r1 + -> Record r2 + -> Record r3 + +-- | Merge a record `mr` with optional default values `o`, resulting in record `mo`. +-- | +-- | The record `mr` must consist of the common fields from `mo` and `mr` plus a subset +-- | of fields from `o`. +-- | +-- | Examples: +-- | * `merge {a:1,b:"Unspecified"} {a:3,c:"Mandatory"} = {a:3,b:"Unspecified",c:"Mandatory"}` +-- | * `merge {a:1,b:"Unspecified"} {c:"Only mandatory"} = {a:1,b:"Unspecified",c:"Only Mandatory"}` +-- | * `merge {a:1,b:"Unspecified"} {a:"Wrong type"} = wont compile` +merge :: forall o mr mo. RecordMerge o mr mo => Record o -> Record mr -> Record mo +merge = unsafeMerge + +-- | Merge record `a` with `b` resulting in `c`. The `Union` constraint means that `c` +-- | will contain all the fields from both `a` and `b`, with `b`'s appearing first in the +-- | list of types. +-- | +-- | Examples: +-- | * `unionMerge {a:"Default"} {a:1} = {a:1} :: {a::Int,a::String}` +-- | * `unionMerge {a:"Default",b:2} {a:1} = {a:1,b:2} :: {a::Int,a::String,b::Int}` +unionMerge :: forall a b c. Union b a c => Record a -> Record b -> Record c +unionMerge = unsafeMerge From d553530acf2c56e0a12a0f3020997947e80db162 Mon Sep 17 00:00:00 2001 From: Athan Clark Date: Sun, 2 Sep 2018 12:58:57 -0600 Subject: [PATCH 2/2] removing clashing imports --- src/Data/Record.purs | 111 ------------------------------------ src/Data/Record/Unsafe.js | 26 --------- src/Data/Record/Unsafe.purs | 23 -------- 3 files changed, 160 deletions(-) delete mode 100644 src/Data/Record.purs delete mode 100644 src/Data/Record/Unsafe.js delete mode 100644 src/Data/Record/Unsafe.purs diff --git a/src/Data/Record.purs b/src/Data/Record.purs deleted file mode 100644 index a76eac5..0000000 --- a/src/Data/Record.purs +++ /dev/null @@ -1,111 +0,0 @@ -module Data.Record - ( get - , set - , modify - , insert - , delete - ) where - -import Data.Function.Uncurried (runFn2, runFn3) -import Data.Record.Unsafe (unsafeGetFn, unsafeSetFn, unsafeDeleteFn) -import Data.Symbol (class IsSymbol, SProxy, reflectSymbol) -import Type.Row (class RowLacks) - --- | Get a property for a label which is specified using a value-level proxy for --- | a type-level string. --- | --- | For example: --- | --- | ```purescript --- | get (SProxy :: SProxy "x") :: forall r a. { x :: a | r } -> a --- | ``` -get - :: forall r r' l a - . IsSymbol l - => RowCons l a r' r - => SProxy l - -> Record r - -> a -get l r = runFn2 unsafeGetFn (reflectSymbol l) r - --- | Set a property for a label which is specified using a value-level proxy for --- | a type-level string. --- | --- | For example: --- | --- | ```purescript --- | set (SProxy :: SProxy "x") --- | :: forall r a b. a -> { x :: b | r } -> { x :: a | r } --- | ``` -set - :: forall r1 r2 r l a b - . IsSymbol l - => RowCons l a r r1 - => RowCons l b r r2 - => SProxy l - -> b - -> Record r1 - -> Record r2 -set l b r = runFn3 unsafeSetFn (reflectSymbol l) b r - --- | Modify a property for a label which is specified using a value-level proxy for --- | a type-level string. --- | --- | For example: --- | --- | ```purescript --- | modify (SProxy :: SProxy "x") --- | :: forall r a b. (a -> b) -> { x :: a | r } -> { x :: b | r } --- | ``` -modify - :: forall r1 r2 r l a b - . IsSymbol l - => RowCons l a r r1 - => RowCons l b r r2 - => SProxy l - -> (a -> b) - -> Record r1 - -> Record r2 -modify l 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. --- | --- | For example: --- | --- | ```purescript --- | insert (SProxy :: SProxy "x") --- | :: forall r a. RowLacks "x" r => a -> { | r } -> { x :: a | r } --- | ``` -insert - :: forall r1 r2 l a - . IsSymbol l - => RowLacks l r1 - => RowCons l a r1 r2 - => SProxy l - -> a - -> Record r1 - -> Record r2 -insert l a r = runFn3 unsafeSetFn (reflectSymbol l) a r - --- | Delete 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 --- | delete (SProxy :: SProxy "x") --- | :: forall r a. RowLacks "x" r => { x :: a | r } -> { | r } --- | ``` -delete - :: forall r1 r2 l a - . IsSymbol l - => RowLacks l r1 - => RowCons l a r1 r2 - => SProxy l - -> Record r2 - -> Record r1 -delete l r = runFn2 unsafeDeleteFn (reflectSymbol l) r diff --git a/src/Data/Record/Unsafe.js b/src/Data/Record/Unsafe.js deleted file mode 100644 index 209e821..0000000 --- a/src/Data/Record/Unsafe.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; - -exports.unsafeGetFn = function(label, rec) { - return rec[label]; -}; - -exports.unsafeSetFn = function(label, value, rec) { - var copy = {}; - for (var key in rec) { - if ({}.hasOwnProperty.call(rec, key)) { - copy[key] = rec[key]; - } - } - copy[label] = value; - return copy; -}; - -exports.unsafeDeleteFn = function(label, rec) { - var copy = {}; - for (var key in rec) { - if (key !== label && {}.hasOwnProperty.call(rec, key)) { - copy[key] = rec[key]; - } - } - return copy; -}; diff --git a/src/Data/Record/Unsafe.purs b/src/Data/Record/Unsafe.purs deleted file mode 100644 index 6d4c1eb..0000000 --- a/src/Data/Record/Unsafe.purs +++ /dev/null @@ -1,23 +0,0 @@ -module Data.Record.Unsafe - ( unsafeGetFn - , unsafeSetFn - , unsafeDeleteFn - , unsafeGet - , unsafeSet - , unsafeDelete - ) where - -import Data.Function.Uncurried (Fn2, Fn3, runFn2, runFn3) - -foreign import unsafeGetFn :: forall r a. Fn2 String (Record r) a -foreign import unsafeSetFn :: forall r1 r2 a. Fn3 String a (Record r1) (Record r2) -foreign import unsafeDeleteFn :: forall r1 r2. Fn2 String (Record r1) (Record r2) - -unsafeGet :: forall r a. String -> Record r -> a -unsafeGet = runFn2 unsafeGetFn - -unsafeSet :: forall r1 r2 a. String -> a -> Record r1 -> Record r2 -unsafeSet = runFn3 unsafeSetFn - -unsafeDelete :: forall r1 r2. String -> Record r1 -> Record r2 -unsafeDelete = runFn2 unsafeDeleteFn