red-black-record 2.1.2.0 → 2.1.3.0
raw patch · 5 files changed
+86/−10 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.RBR: class (f x, g x) => And (f :: k -> Constraint) (g :: k -> Constraint) (x :: k)
+ Data.RBR: class Top (x :: k)
+ Data.RBR: infixl 7 `And`
+ Data.RBR: injections_Record :: Maplike t => Record (Case f (Endo (Record f t))) t
+ Data.RBR: unI :: () => I a -> a
+ Data.RBR: unK :: () => K a b -> a
+ Data.RBR.Internal: injections_Record :: Maplike t => Record (Case f (Endo (Record f t))) t
Files
- CHANGELOG.md +3/−0
- lib/Data/RBR.hs +5/−1
- lib/Data/RBR/Internal.hs +21/−3
- lib/Data/RBR/Subset.hs +56/−5
- red-black-record.cabal +1/−1
CHANGELOG.md view
@@ -1,5 +1,8 @@ # Revision history for red-black-record +## 2.1.3.0+- Added injections_Record. + ## 2.1.2.0 - Deprecated VariantInjection and injections_Variant. VariantInjections is superfluous, as Case can be used instead.
lib/Data/RBR.hs view
@@ -105,10 +105,14 @@ fromNS, -- * Data.SOP re-exports I(..),+ unI, K(..),+ unK, NP(..), NS(..), (:.:)(..),+ And,+ Top, -- * Deprecated collapse_Record, injections_Variant,@@ -132,7 +136,7 @@ ) where import Data.RBR.Internal-import Data.SOP (I(..),K(..),NP(..),NS(..),(:.:)(..),Top)+import Data.SOP (I(..),unI,K(..),unK,NP(..),NS(..),(:.:)(..),And,Top) {- $setup
lib/Data/RBR/Internal.hs view
@@ -144,13 +144,18 @@ -} liftA2_Variant :: (forall a. f a -> g a -> h a) -> Record f t -> Variant g t -> Variant h t {- | - Construct a 'Record' made of functions which take a value of the+ Constructs a 'Record' made of functions which take a value of the field's type and inject it in the 'Variant' branch which corresponds to the field. Compare to 'Data.SOP.NS.injections' from @generics-sop@. -} injections'_Variant :: Record (Case f (Variant f t)) t+ {- | + Constructs a 'Record' made of functions which take a value of the+ field's type and return a record updater function that sets the field.+ -}+ injections_Record :: Record (Case f (Endo (Record f t))) t {- | Collapse a 'Record' composed of 'K' monoidal annotations. >>> collapse'_Record (unit :: Record (K [Bool]) Empty)@@ -174,6 +179,7 @@ liftA_Variant _ neverHappens = impossible neverHappens liftA2_Variant _ Empty neverHappens = impossible neverHappens injections'_Variant = Empty+ injections_Record = Empty collapse'_Record Empty = mempty collapse_Variant = impossible @@ -195,6 +201,19 @@ let injections_Left = liftA_Record (\(Case j) -> Case $ LookLeft . j) (injections'_Variant @left) injections_Right = liftA_Record (\(Case j) -> Case $ LookRight . j) (injections'_Variant @right) in Node injections_Left (Case $ Here) injections_Right+ injections_Record = + Node + (liftA_Record (\(Case cleft) -> + (Case $ \x -> + Endo $ (\(Node left' x' right') -> Node (appEndo (cleft x) left') x' right')))++ (injections_Record @left))+ (Case $ \x -> Endo $ \(Node left v right) -> Node left x right) + (liftA_Record (\(Case cright) -> + (Case $ \x -> + Endo $ (\(Node left' x' right') -> Node left' x' (appEndo (cright x) right'))))++ (injections_Record @right)) collapse'_Record (Node left (K v) right) = collapse'_Record left <> (v <> collapse'_Record right) collapse_Variant vv = case vv of Here (K a) -> a@@ -286,7 +305,6 @@ >>> putStrLn $ prettyShow_Record show $ demoteEntries @(FromList [ '("foo",Char), '("bar",Bool) ]) {bar = K ("bar",Bool), foo = K ("foo",Char)} - See also 'collapse_Record' for getting the entries as a list. -} demoteEntries :: forall t. KeysValuesAll KnownKeyTypeableValue t => Record (K (String,TypeRep)) t demoteEntries = cpara_Map (Proxy @KnownKeyTypeableValue) unit go@@ -327,7 +345,7 @@ {- | An extensible product-like type with named fields. The values in the 'Record' come wrapped in a type constructor @f@, which- por pure records will be the identity functor 'I'.+ for pure records will be the identity functor 'I'. See also 'insert', 'delete' and 'project'. -}
lib/Data/RBR/Subset.hs view
@@ -1,9 +1,46 @@ {-| - This module contains versions of functions from 'Data.RBR', generalized to+ This module contains versions of functions from "Data.RBR", generalized to work with a subset of the fields of a 'Record' or the branches of a 'Variant'.++ Besides working with subsets of fields and branches, this module is useful+ for another thing. The equality of type-level trees is unfortunately too+ strict: inserting the same elements but in /different order/ can result in+ structurally different trees, which in its turn causes annoying errors when+ trying to combine 'Record's, even as they have exactly the same fields.++ To solve these kinds of problems, functions like 'projectSubset' can be+ used to transform 'Record's indexed by one map into records indexed by+ another.++ For example, consider this code:++>>> :{+ prettyShow_RecordI $+ liftA2_Record+ (\_ x -> x)+ ( id+ $ S.projectSubset @(FromList ['("bar", _), '("foo", _)]) -- rearrange+ $ insertI @"foo"+ 'a'+ $ insertI @"bar"+ True+ $ unit+ )+ ( id+ $ insertI @"bar"+ True+ $ insertI @"foo"+ 'a'+ $ unit+ )+:}+"{bar = True, foo = 'a'}"++ If we remove the 'projectSubset' line that rearranges the structure of the+ first record's index map, the code ceases to compile. - __Note:__ There are functions of the same name in the 'Data.RBR' module,+ __Note:__ There are functions of the same name in the "Data.RBR" module, but they are deprecated. The functions from this module should be used instead, preferably qualified. The changes have to do mainly with the required constraints.@@ -32,15 +69,19 @@ #-} {-# OPTIONS_GHC -Wno-partial-type-signatures #-} module Data.RBR.Subset (+ -- * The subset constraint Subset,+ -- * Record subset functions fieldSubset, projectSubset, getFieldSubset, setFieldSubset, modifyFieldSubset,+ -- * Variant subset functions branchSubset, injectSubset, matchSubset, + -- * Miscellany functions fromRecordSuperset, eliminateSubset ) where@@ -77,7 +118,7 @@ -} -{- | A map is a subset of another if all of its entries are present in the other map.+{- | A type-level map is a subset of another if all of its entries are present in the other map. -} type Subset (subset :: Map Symbol q) (whole :: Map Symbol q) = KeysValuesAll (PresentIn whole) subset@@ -114,10 +155,20 @@ The types in the subset tree can often be inferred and left as wildcards in type signature. ->>> prettyShow_RecordI $ S.projectSubset @(Insert "foo" _ (Insert "bar" _ Empty)) (insertI @"foo" 'a' (insertI @"bar" True (insertI @"baz" (Just ()) unit)))+>>> :{ + prettyShow_RecordI+ $ S.projectSubset @(FromList ['("foo", _), '("bar", _)])+ $ insertI @"foo"+ 'a'+ $ insertI @"bar"+ True+ $ insertI @"baz"+ (Just ())+ $ unit+:} "{bar = True, foo = 'a'}" - Can also be used to convert between 'Record's with structurally dissimilar+ This function also be used to convert between 'Record's with structurally dissimilar type-level maps that nevertheless hold the same entries. -} projectSubset :: forall subset whole f. (Maplike subset, Subset subset whole)
red-black-record.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.0 name: red-black-record-version: 2.1.2.0+version: 2.1.3.0 synopsis: Extensible records and variants indexed by a type-level Red-Black tree. description: A library that provides extensible records and variants,