aeson-diff-generic 0.0.2 → 0.0.3
raw patch · 4 files changed
+240/−5 lines, 4 filesdep +lensPVP ok
version bump matches the API change (PVP)
Dependencies added: lens
API changes (from Hackage documentation)
+ Data.Aeson.Diff.Generic.PathOptics: _10P :: Field10 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _11P :: Field11 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _12P :: Field12 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _13P :: Field13 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _14P :: Field14 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _15P :: Field15 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _16P :: Field16 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _17P :: Field17 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _18P :: Field18 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _19P :: Field19 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _1P :: Field1 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _2P :: Field2 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _3P :: Field3 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _4P :: Field4 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _5P :: Field5 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _6P :: Field6 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _7P :: Field7 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _8P :: Field8 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _9P :: Field9 s s a a => PathLens s a
+ Data.Aeson.Diff.Generic.PathOptics: _JustP :: Traversal' (Path, Maybe a) (Path, a)
+ Data.Aeson.Diff.Generic.PathOptics: _LeftP :: Traversal' (Path, Either a b) (Path, a)
+ Data.Aeson.Diff.Generic.PathOptics: _RightP :: Traversal' (Path, Either a b) (Path, b)
+ Data.Aeson.Diff.Generic.PathOptics: append :: Appendable a => (IxValue a) -> a -> a
+ Data.Aeson.Diff.Generic.PathOptics: appendPath :: (ToJSON (IxValue a), Appendable a) => IxValue a -> PathTraversal s a -> s -> (Patch, s)
+ Data.Aeson.Diff.Generic.PathOptics: class KeyIndexed a => Appendable a
+ Data.Aeson.Diff.Generic.PathOptics: class KeyIndexed a => Insertable a
+ Data.Aeson.Diff.Generic.PathOptics: class KeyIndexed s
+ Data.Aeson.Diff.Generic.PathOptics: deleteKey :: Insertable a => Index a -> a -> Maybe (IxValue a, a)
+ Data.Aeson.Diff.Generic.PathOptics: deletePath :: (ToJSON (IxValue a), Insertable a) => Index a -> PathTraversal s a -> s -> (Patch, s)
+ Data.Aeson.Diff.Generic.PathOptics: getPath :: PathTraversal s a -> s -> [(Pointer, a)]
+ Data.Aeson.Diff.Generic.PathOptics: insertKey :: Insertable a => Index a -> (IxValue a) -> a -> a
+ Data.Aeson.Diff.Generic.PathOptics: insertPath :: (ToJSON (IxValue a), Insertable a) => Index a -> IxValue a -> PathTraversal s a -> s -> (Patch, s)
+ Data.Aeson.Diff.Generic.PathOptics: ixP :: (KeyIndexed s, Ixed s) => Index s -> Traversal' (Path, s) (Path, IxValue s)
+ Data.Aeson.Diff.Generic.PathOptics: overPath :: ToJSON a => PathTraversal s a -> (a -> a) -> s -> (Patch, s)
+ Data.Aeson.Diff.Generic.PathOptics: replacePath :: ToJSON a => PathTraversal s a -> a -> s -> (Patch, s)
+ Data.Aeson.Diff.Generic.PathOptics: testPath :: ToJSON a => PathTraversal s a -> s -> (Patch, s)
+ Data.Aeson.Diff.Generic.PathOptics: toKey :: KeyIndexed s => Index s -> s -> Key
+ Data.Aeson.Diff.Generic.PathOptics: traverseP :: (a ~ Index (s a), TraversableWithIndex a s, KeyIndexed (s a)) => Traversal' (Path, (s a)) (Path, a)
+ Data.Aeson.Diff.Generic.PathOptics: type PathLens s a = Lens' (Path, s) (Path, a)
+ Data.Aeson.Diff.Generic.PathOptics: type PathTraversal s a = Traversal' (Path, s) (Path, a)
+ Data.Aeson.Diff.Generic.PathOptics: withPath :: Functor f => Path -> ((a -> Compose f ((,) Path) a) -> (s -> Compose f ((,) Path) s)) -> (((Path, a) -> f (Path, a)) -> (Path, s) -> f (Path, s))
+ Data.Aeson.Diff.Generic.PathOptics: withoutPath :: Functor f => (((Path, a) -> f (Path, a)) -> ((Path, s) -> f (Path, s))) -> ((a -> f a) -> (s -> f s))
Files
- Data/Aeson/Diff/Generic/PathOptics.hs +229/−0
- README.md +3/−3
- aeson-diff-generic.cabal +5/−2
- changelog.md +3/−0
+ Data/Aeson/Diff/Generic/PathOptics.hs view
@@ -0,0 +1,229 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE DefaultSignatures #-}++module Data.Aeson.Diff.Generic.PathOptics+ ( -- * type synonyms+ PathLens, PathTraversal,+ -- * operations over path optics+ overPath, replacePath, getPath, appendPath,+ insertPath, deletePath, testPath,+ KeyIndexed(..), Insertable(..), Appendable(..),+ -- * creating and extracting path optics+ withPath, withoutPath,+ -- * pathOptics+ ixP, traverseP, _1P, _2P, _3P, _4P, _5P,+ _6P, _7P, _8P, _9P, _10P, _11P, _12P, _13P,+ _14P, _15P, _16P, _17P, _18P, _19P, _LeftP, _RightP,+ _JustP)++where+import Prelude()+import Prelude.Compat+import Data.Aeson+import Data.Aeson.Diff+import Data.Aeson.Pointer+import Data.Monoid+import Data.Functor.Compose+import Control.Lens++type PathTraversal s a = Traversal' (Path, s) (Path, a)+type PathLens s a = Lens' (Path, s) (Path, a)++class KeyIndexed s where+ toKey :: Index s -> s -> Key++class KeyIndexed a => Insertable a where+ insertKey :: Index a -> (IxValue a) -> a -> a+ deleteKey :: Index a -> a -> Maybe (IxValue a, a)++class KeyIndexed a => Appendable a where+ append :: (IxValue a) -> a -> a++-- | Annotate an optic with a path. The output optic will be the same+-- optic, with a path annotation. For example:+--+-- > withPath :: Path -> Lens' s a -> Lens' (Path, s) (Path, a)+-- > withPath :: Path -> Traversal' s a -> Traversal' (Path, s) (Path, a)++withPath :: Functor f + => Path -- ^ the path into the structure+ -> ((a -> Compose f ((,) Path) a) -> (s -> Compose f ((,) Path) s))+ -- ^ the input optic+ -> (((Path, a) -> f (Path, a)) -> (Path, s) -> f (Path, s))+ -- ^ the output optic with path information+withPath p2 orig f (p, v) =+ fmap (over _1 (p <>)) $ getCompose $+ orig (\a -> Compose $ f (p2,a)) v++-- | remove the path from an optic annotated with path information.+-- +-- > withoutPath . withPath ≡ id+--+-- The output optic will be the same+-- optic, without the path annotation. For example:+--+-- > withoutPath :: Lens' (Path, s) (Path, a) -> Lens' s a+-- > withoutPath :: Traversal' (Path, s) (Path, a) -> Traversal' s a+withoutPath :: Functor f+ => (((Path, a) -> f (Path, a)) -> ((Path, s) -> f (Path, s)))+ -- ^ input optic+ -> ((a -> f a) -> (s -> f s))+ -- ^ output optic without path information+withoutPath l f v = snd <$> l (traverseOf _2 f) (rootPath, v)++-- | the root path+rootPath :: Path+rootPath = []++-- | Modify the value(s) at the traversal, and return a patch which+-- represents those (replace) operations.+overPath :: ToJSON a => PathTraversal s a -> (a -> a) -> s -> (Patch, s)+overPath lns f s =+ snd <$>+ lns (\(p2, a) ->+ let a2 = f a in+ ( Patch [Rep (Pointer p2) (toJSON a2)]+ , (p2, a2)))+ (rootPath, s)+ +-- | Replace the value at the traversal, and return a patch with+-- the replace operations.+replacePath :: ToJSON a => PathTraversal s a -> a -> s -> (Patch, s)+replacePath lns = overPath lns . const++-- | Return the values and pointers pointed to by the traversal (if any)+getPath :: PathTraversal s a -> s -> [(Pointer, a)]+getPath lns v = over _1 Pointer <$> (rootPath, v) ^.. lns++-- | Append a value to the structure pointed by the lens. Return a+-- patch which the append operations)+appendPath :: (ToJSON (IxValue a), Appendable a)+ => IxValue a -> PathTraversal s a -> s -> (Patch, s)+appendPath v lns s =+ snd <$>+ lns (\(p2, a) ->+ let a2 = append v a+ in ( Patch [Add (Pointer $ p2 ++ [OKey "-"]) (toJSON v)]+ , (p2, a2)))+ (rootPath, s)++-- | Insert a value at the given key, and return a patch with the+-- insert operations+insertPath :: (ToJSON (IxValue a), Insertable a)+ => Index a -> IxValue a -> PathTraversal s a -> s+ -> (Patch, s)+insertPath key v lns s =+ fmap snd $+ lns (\(p2, a) ->+ let a2 = insertKey key v a+ in ( Patch [Add (Pointer $ p2 <>+ [toKey key a]) (toJSON v)]+ , (p2, a2)))+ (rootPath, s) ++-- | Delete a value at the given key if present, and return a patch+-- with the delete operations.+deletePath :: (ToJSON (IxValue a), Insertable a)+ => Index a -> PathTraversal s a -> s+ -> (Patch, s)+deletePath key lns s =+ fmap snd $+ lns (\(p2, a) ->+ case deleteKey key a of+ Nothing -> (Patch [], (p2, a))+ Just (_, a2) ->+ ( Patch [Rem (Pointer $ p2 <> [toKey key a])]+ , (p2, a2)))+ (rootPath, s) ++-- | Create a patch that tests if the value at the pointer equals the+-- current value. Returns the data unmodified.+testPath :: ToJSON a => PathTraversal s a -> s -> (Patch, s)+testPath lns s =+ ( Patch $ (\(ptr, v) -> Tst ptr (toJSON v)) <$> getPath lns s+ , s)++-- | `ix` from lens annotated with a path. Provides a simple+-- Traversal lets you traverse the value at a given key in a Map or+-- element at an ordinal position in a list or Seq. Includes the path+-- to the element.+ixP :: (KeyIndexed s, Ixed s) =>+ Index s -> Traversal' (Path, s) (Path, IxValue s)+ixP i f s = (withPath [toKey i (snd s)] (ix i)) f s++traverseP :: (a ~ Index (s a), TraversableWithIndex a s, + KeyIndexed (s a))+ => Traversal' (Path, (s a)) (Path, a)+traverseP f (p, s) =+ fmap (over _1 (p <>)) $ getCompose $+ itraverse (\i a -> Compose (f ([toKey i s], a))) s++_1P :: Field1 s s a a => PathLens s a+_1P = withPath [AKey 0] _1++_2P :: Field2 s s a a => PathLens s a+_2P = withPath [AKey 1] _2++_3P :: Field3 s s a a => PathLens s a+_3P = withPath [AKey 2] _3++_4P :: Field4 s s a a => PathLens s a+_4P = withPath [AKey 3] _4++_5P :: Field5 s s a a => PathLens s a+_5P = withPath [AKey 4] _5++_6P :: Field6 s s a a => PathLens s a+_6P = withPath [AKey 5] _6++_7P :: Field7 s s a a => PathLens s a+_7P = withPath [AKey 6] _7++_8P :: Field8 s s a a => PathLens s a+_8P = withPath [AKey 7] _8++_9P :: Field9 s s a a => PathLens s a+_9P = withPath [AKey 8] _9++_10P :: Field10 s s a a => PathLens s a+_10P = withPath [AKey 9] _10++_11P :: Field11 s s a a => PathLens s a+_11P = withPath [AKey 10] _11++_12P :: Field12 s s a a => PathLens s a+_12P = withPath [AKey 11] _12++_13P :: Field13 s s a a => PathLens s a+_13P = withPath [AKey 12] _13++_14P :: Field14 s s a a => PathLens s a+_14P = withPath [AKey 13] _14++_15P :: Field15 s s a a => PathLens s a+_15P = withPath [AKey 14] _15++_16P :: Field16 s s a a => PathLens s a+_16P = withPath [AKey 15] _16++_17P :: Field17 s s a a => PathLens s a+_17P = withPath [AKey 16] _17++_18P :: Field18 s s a a => PathLens s a+_18P = withPath [AKey 17] _18++_19P :: Field19 s s a a => PathLens s a+_19P = withPath [AKey 18] _19++_LeftP :: Traversal' (Path, Either a b) (Path, a)+_LeftP = withPath [OKey "Left"] _Left++_RightP :: Traversal' (Path, Either a b) (Path, b)+_RightP = withPath [OKey "Right"] _Right++_JustP :: Traversal' (Path, Maybe a) (Path, a)+_JustP = withPath [] _Just
README.md view
@@ -18,8 +18,8 @@ The aeson library uses GHC.Generics or template haskell to define a default json encoding for algebraic datatypes. The aeson-diff-generic-can generate code, using options given to aeson, to interpret a json-patch as a Doc patch.+can generate code, using the same options as given to aeson, to+interpret a json patch as a Doc patch. # Example @@ -72,7 +72,7 @@ fieldLens _ _ = Error "Invalid Path" ``` -Since this is the default implementation, so we can do simply:+Since this is the default implementation, we can do simply: ```haskell instance FieldLens Pet
aeson-diff-generic.cabal view
@@ -1,5 +1,5 @@ Name: aeson-diff-generic-Version: 0.0.2+Version: 0.0.3 Synopsis: Apply a json-patch to any haskell datatype. Category: JSON, Web Copyright: Kristof Bastiaensen (2018)@@ -47,7 +47,9 @@ time >= 1.1.1.4, unordered-containers >= 0.2.5.0 && < 0.3, uuid-types >= 1.0.3 && <1.1,- vector >= 0.8+ vector >= 0.8,+ lens >= 4.16 && < 4.17+ if !impl(ghc >= 8.0) -- `Data.Semigroup` and `Control.Monad.Fail` and `Control.Monad.IO.Class` are available in base only since GHC 8.0 / base 4.9@@ -64,6 +66,7 @@ Exposed-Modules: Data.Aeson.Diff.Generic Data.Aeson.Diff.Generic.TH Data.Aeson.Diff.Generic.Instances+ Data.Aeson.Diff.Generic.PathOptics Other-Modules: Data.Aeson.Diff.Generic.Types
changelog.md view
@@ -1,5 +1,8 @@ # aeson-diff-generic 0.0.2 +*April 17, 2018*+ - Implement path optics.+ *April 2, 2018* - Better documentation.