on develop help sign in
Merge branch 'develop' of github.com:reflex-frp/patch into dpatch-map-inner-patch
6fcf213John Ericson
ChangeLog.md+12
@@ -6,6 +6,18 @@
6
6
7* `PatchDMapWithMove` supports moves with a patch.
7* `PatchDMapWithMove` supports moves with a patch.
8
8
9+## 0.0.2.0
10+
11+* Consistently provide:
12+
13+ - `Wrapped` instances
14+
15+ - `*WithIndex` instances
16+
17+ - `un*` newtype unwrappers
18+
19+ for `PatchMap`, `PatchIntMap`, and `PatchMapWithMove`.
20+
9## 0.0.1.0
21## 0.0.1.0
10
22
11* Support older GHCs with `split-these` flag.
23* Support older GHCs with `split-these` flag.
dep/reflex-platform/default.nix+7−6
@@ -1,7 +1,8 @@
1# DO NOT HAND-EDIT THIS FILE
1# DO NOT HAND-EDIT THIS FILE
2+let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
3+ if !fetchSubmodules && !private then builtins.fetchTarball {
4+ url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
2−import ((import <nixpkgs> {}).fetchFromGitHub (
5+ } else (import <nixpkgs> {}).fetchFromGitHub {
6+ inherit owner repo rev sha256 fetchSubmodules private;
7+ };
3− let json = builtins.fromJSON (builtins.readFile ./github.json);
8+in import (fetch (builtins.fromJSON (builtins.readFile ./github.json)))
4− in { inherit (json) owner repo rev sha256;
5− private = json.private or false;
6− }
7−))
dep/reflex-platform/github.json+3−2
@@ -2,6 +2,7 @@
2 "owner": "reflex-frp",
2 "owner": "reflex-frp",
3 "repo": "reflex-platform",
3 "repo": "reflex-platform",
4 "branch": "master",
4 "branch": "master",
5− "rev": "510b990d0b11f0626afbec5fe8575b5b2395391b",
5+ "private": false,
6− "sha256": "09cmahsbxr0963wq171c7j139iyzz49hramr4v9nsf684wcwkngv"
6+ "rev": "c9d11db1b98855fe8ab24a3ff6a5dbe0ad902ad9",
7+ "sha256": "0sfzkqdvyah5mwvmli0wq1nl0b8cvk2cmfgfy4rz57wv42x3099y"
7}
8}
patch.cabal+2−1
@@ -1,5 +1,5 @@
1Name: patch
1Name: patch
2−Version: 0.0.1.0
2+Version: 0.0.2.0
3Synopsis: Infrastructure for writing patches which act on other types.
3Synopsis: Infrastructure for writing patches which act on other types.
4Description:
4Description:
5 In this library, a patch is something which can be applied, analogous to a
5 In this library, a patch is something which can be applied, analogous to a
@@ -35,6 +35,7 @@ library
35 , containers >= 0.6 && < 0.7
35 , containers >= 0.6 && < 0.7
36 , dependent-map >= 0.3 && < 0.4
36 , dependent-map >= 0.3 && < 0.4
37 , dependent-sum >= 0.6 && < 0.7
37 , dependent-sum >= 0.6 && < 0.7
38+ , lens >= 4.7 && < 5
38 , semigroupoids >= 4.0 && < 6
39 , semigroupoids >= 4.0 && < 6
39 , transformers >= 0.5.6.0 && < 0.6
40 , transformers >= 0.5.6.0 && < 0.6
40 , witherable >= 0.3 && < 0.3.2
41 , witherable >= 0.3 && < 0.3.2
release.nix+20−10
@@ -18,16 +18,26 @@ let
18 "ghcIosAarch64"
18 "ghcIosAarch64"
19 ];
19 ];
20 compilerPkgs = lib.genAttrs compilers (ghc: let
20 compilerPkgs = lib.genAttrs compilers (ghc: let
21+ reflex-platform = reflex-platform-fun {
22+ inherit system;
23+ haskellOverlays = [
24+ # Use this package's source for reflex
25+ (self: super: {
26+ _dep = super._dep // {
21− src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [
27+ patch = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [
22− "release.nix"
28+ "release.nix"
23− ".git"
29+ ".git"
24− "dist"
30+ "dist"
25− "dist-newstyle"
31+ "dist-newstyle"
26− "cabal.haskell-ci"
32+ "cabal.haskell-ci"
27− "cabal.project"
33+ "cabal.project"
28− ".travis.yml"
34+ ".travis.yml"
29− ])) ./.;
35+ ])) ./.;
36+ };
37+ })
38+ ];
39+ };
30− in reflex-platform.${ghc}.callCabal2nix "patch" src {});
40+ in reflex-platform.${ghc}.patch);
31 in compilerPkgs // {
41 in compilerPkgs // {
32 cache = reflex-platform.pinBuildInputs "patch-${system}"
42 cache = reflex-platform.pinBuildInputs "patch-${system}"
33 (builtins.attrValues compilerPkgs);
43 (builtins.attrValues compilerPkgs);
src/Data/Patch/IntMap.hs+24−10
@@ -1,12 +1,15 @@
1−{-# LANGUAGE DeriveFoldable #-}
2−{-# LANGUAGE DeriveFunctor #-}
3{-# LANGUAGE DeriveTraversable #-}
1{-# LANGUAGE DeriveTraversable #-}
2+{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+{-# LANGUAGE MultiParamTypeClasses #-}
5+{-# LANGUAGE TemplateHaskell #-}
5{-# LANGUAGE TypeFamilies #-}
6{-# LANGUAGE TypeFamilies #-}
7+
6-- | Module containing 'PatchIntMap', a 'Patch' for 'IntMap' which allows for
8-- | Module containing 'PatchIntMap', a 'Patch' for 'IntMap' which allows for
7-- insert/update or delete of associations.
9-- insert/update or delete of associations.
8module Data.Patch.IntMap where
10module Data.Patch.IntMap where
9
11
12+import Control.Lens
10import Data.IntMap.Strict (IntMap)
13import Data.IntMap.Strict (IntMap)
11import qualified Data.IntMap.Strict as IntMap
14import qualified Data.IntMap.Strict as IntMap
12import Data.Maybe
15import Data.Maybe
@@ -16,7 +19,20 @@ import Data.Patch.Class
16-- | 'Patch' for 'IntMap' which represents insertion or deletion of keys in the mapping.
19-- | 'Patch' for 'IntMap' which represents insertion or deletion of keys in the mapping.
17-- Internally represented by 'IntMap (Maybe a)', where @Just@ means insert/update
20-- Internally represented by 'IntMap (Maybe a)', where @Just@ means insert/update
18-- and @Nothing@ means delete.
21-- and @Nothing@ means delete.
19−newtype PatchIntMap a = PatchIntMap (IntMap (Maybe a)) deriving (Functor, Foldable, Traversable, Monoid)
22+newtype PatchIntMap a = PatchIntMap { unPatchIntMap :: IntMap (Maybe a) }
23+ deriving ( Show, Read, Eq, Ord
24+ , Functor, Foldable, Traversable, Monoid
25+ )
26+
27+-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
28+-- If the same key is modified by both patches, the one on the left will take
29+-- precedence.
30+instance Semigroup (PatchIntMap v) where
31+ PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b --TODO: Add a semigroup instance for Map
32+ -- PatchMap is idempotent, so stimes n is id for every n
33+ stimes = stimesIdempotentMonoid
34+
35+makeWrapped ''PatchIntMap
20
36
21-- | Apply the insertions or deletions to a given 'IntMap'.
37-- | Apply the insertions or deletions to a given 'IntMap'.
22instance PatchHet (PatchIntMap a) where
38instance PatchHet (PatchIntMap a) where
@@ -28,13 +44,11 @@ instance Patch (PatchIntMap a) where
28 adds = IntMap.mapMaybe id p
44 adds = IntMap.mapMaybe id p
29 in IntMap.union adds $ v `IntMap.difference` removes
45 in IntMap.union adds $ v `IntMap.difference` removes
30
46
31−-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
47+instance FunctorWithIndex Int PatchIntMap
32−-- If the same key is modified by both patches, the one on the left will take
48+instance FoldableWithIndex Int PatchIntMap
33−-- precedence.
49+instance TraversableWithIndex Int PatchIntMap where
34−instance Semigroup (PatchIntMap v) where
50+ itraverse = itraversed . Indexed
35− PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b --TODO: Add a semigroup instance for Map
51+ itraversed = _Wrapped .> itraversed <. traversed
36− -- PatchMap is idempotent, so stimes n is id for every n
37− stimes = stimesIdempotentMonoid
38
52
39-- | Map a function @Int -> a -> b@ over all @a@s in the given @'PatchIntMap' a@
53-- | Map a function @Int -> a -> b@ over all @a@s in the given @'PatchIntMap' a@
40-- (that is, all inserts/updates), producing a @PatchIntMap b@.
54-- (that is, all inserts/updates), producing a @PatchIntMap b@.
src/Data/Patch/Map.hs+29−13
@@ -1,11 +1,18 @@
1+{-# LANGUAGE DeriveTraversable #-}
2+{-# LANGUAGE FlexibleInstances #-}
1{-# LANGUAGE LambdaCase #-}
3{-# LANGUAGE LambdaCase #-}
4+{-# LANGUAGE MultiParamTypeClasses #-}
5+{-# LANGUAGE StandaloneDeriving #-}
6+{-# LANGUAGE TemplateHaskell #-}
2{-# LANGUAGE TypeFamilies #-}
7{-# LANGUAGE TypeFamilies #-}
8+
3-- | 'Patch'es on 'Map' that consist only of insertions (including overwrites)
9-- | 'Patch'es on 'Map' that consist only of insertions (including overwrites)
4-- and deletions
10-- and deletions
5module Data.Patch.Map where
11module Data.Patch.Map where
6
12
7import Data.Patch.Class
13import Data.Patch.Class
8
14
15+import Control.Lens
9import Data.Map (Map)
16import Data.Map (Map)
10import qualified Data.Map as Map
17import qualified Data.Map as Map
11import Data.Maybe
18import Data.Maybe
@@ -15,7 +22,23 @@ import Data.Semigroup
15-- deleted. Insertions are represented as values wrapped in 'Just', while
22-- deleted. Insertions are represented as values wrapped in 'Just', while
16-- deletions are represented as 'Nothing's
23-- deletions are represented as 'Nothing's
17newtype PatchMap k v = PatchMap { unPatchMap :: Map k (Maybe v) }
24newtype PatchMap k v = PatchMap { unPatchMap :: Map k (Maybe v) }
18− deriving (Show, Read, Eq, Ord)
25+ deriving ( Show, Read, Eq, Ord
26+ , Foldable, Traversable
27+ )
28+
29+-- | 'fmap'ping a 'PatchMap' will alter all of the values it will insert.
30+-- Deletions are unaffected.
31+deriving instance Functor (PatchMap k)
32+
33+-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
34+-- If the same key is modified by both patches, the one on the left will take
35+-- precedence.
36+instance Ord k => Semigroup (PatchMap k v) where
37+ PatchMap a <> PatchMap b = PatchMap $ a `mappend` b --TODO: Add a semigroup instance for Map
38+ -- PatchMap is idempotent, so stimes n is id for every n
39+ stimes = stimesIdempotentMonoid
40+
41+makeWrapped ''PatchMap
19
42
20-- | Apply the insertions or deletions to a given 'Map'.
43-- | Apply the insertions or deletions to a given 'Map'.
21instance Ord k => PatchHet (PatchMap k v) where
44instance Ord k => PatchHet (PatchMap k v) where
@@ -30,24 +53,17 @@ instance Ord k => Patch (PatchMap k v) where
30 Nothing -> Just ()
53 Nothing -> Just ()
31 Just _ -> Nothing
54 Just _ -> Nothing
32
55
33−-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
56+instance FunctorWithIndex k (PatchMap k)
34−-- If the same key is modified by both patches, the one on the left will take
57+instance FoldableWithIndex k (PatchMap k)
35−-- precedence.
36−instance Ord k => Semigroup (PatchMap k v) where
58+instance TraversableWithIndex k (PatchMap k) where
37− PatchMap a <> PatchMap b = PatchMap $ a `mappend` b --TODO: Add a semigroup instance for Map
59+ itraverse = itraversed . Indexed
38− -- PatchMap is idempotent, so stimes n is id for every n
60+ itraversed = _Wrapped .> itraversed <. traversed
39− stimes = stimesIdempotentMonoid
40
61
41-- | The empty 'PatchMap' contains no insertions or deletions
62-- | The empty 'PatchMap' contains no insertions or deletions
42instance Ord k => Monoid (PatchMap k v) where
63instance Ord k => Monoid (PatchMap k v) where
43 mempty = PatchMap mempty
64 mempty = PatchMap mempty
44 mappend = (<>)
65 mappend = (<>)
45
66
46−-- | 'fmap'ping a 'PatchMap' will alter all of the values it will insert.
47−-- Deletions are unaffected.
48−instance Functor (PatchMap k) where
49− fmap f = PatchMap . fmap (fmap f) . unPatchMap
50−
51-- | Returns all the new elements that will be added to the 'Map'
67-- | Returns all the new elements that will be added to the 'Map'
52patchMapNewElements :: PatchMap k v -> [v]
68patchMapNewElements :: PatchMap k v -> [v]
53patchMapNewElements (PatchMap p) = catMaybes $ Map.elems p
69patchMapNewElements (PatchMap p) = catMaybes $ Map.elems p
src/Data/Patch/MapWithMove.hs+17−11
@@ -1,11 +1,17 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2+{-# LANGUAGE DeriveTraversable #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE LambdaCase #-}
5{-# LANGUAGE LambdaCase #-}
6+{-# LANGUAGE MultiParamTypeClasses #-}
4{-# LANGUAGE PatternGuards #-}
7{-# LANGUAGE PatternGuards #-}
5{-# LANGUAGE ScopedTypeVariables #-}
8{-# LANGUAGE ScopedTypeVariables #-}
6{-# LANGUAGE StandaloneDeriving #-}
9{-# LANGUAGE StandaloneDeriving #-}
10+{-# LANGUAGE TemplateHaskell #-}
11+{-# LANGUAGE TypeApplications #-}
7{-# LANGUAGE TypeFamilies #-}
12{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE UndecidableInstances #-}
13{-# LANGUAGE UndecidableInstances #-}
14+
9-- | 'Patch'es on 'Map' that can insert, delete, and move values from one key to
15-- | 'Patch'es on 'Map' that can insert, delete, and move values from one key to
10-- another
16-- another
11module Data.Patch.MapWithMove where
17module Data.Patch.MapWithMove where
@@ -13,6 +19,7 @@ module Data.Patch.MapWithMove where
13import Data.Patch.Class
19import Data.Patch.Class
14
20
15import Control.Arrow
21import Control.Arrow
22+import Control.Lens hiding (from, to)
16import Control.Monad.Trans.State
23import Control.Monad.Trans.State
17import Data.Foldable
24import Data.Foldable
18import Data.Function
25import Data.Function
@@ -31,8 +38,12 @@ import Data.Tuple
31-- | Patch a Map with additions, deletions, and moves. Invariant: If key @k1@
38-- | Patch a Map with additions, deletions, and moves. Invariant: If key @k1@
32-- is coming from @From_Move k2@, then key @k2@ should be going to @Just k1@,
39-- is coming from @From_Move k2@, then key @k2@ should be going to @Just k1@,
33-- and vice versa. There should never be any unpaired From/To keys.
40-- and vice versa. There should never be any unpaired From/To keys.
34−newtype PatchMapWithMove k p = PatchMapWithMove (Map k (NodeInfo k p))
41+newtype PatchMapWithMove k p = PatchMapWithMove
42+ { -- | Extract the internal representation of the 'PatchMapWithMove'
43+ unPatchMapWithMove :: Map k (NodeInfo k p)
44+ }
35deriving instance (Show k, Show p, Show (PatchTarget p)) => Show (PatchMapWithMove k p)
45deriving instance (Show k, Show p, Show (PatchTarget p)) => Show (PatchMapWithMove k p)
46+deriving instance (Ord k, Read k, Read p, Read (PatchTarget p)) => Read (PatchMapWithMove k p)
36deriving instance (Eq k, Eq p, Eq (PatchTarget p)) => Eq (PatchMapWithMove k p)
47deriving instance (Eq k, Eq p, Eq (PatchTarget p)) => Eq (PatchMapWithMove k p)
37deriving instance (Ord k, Ord p, Ord (PatchTarget p)) => Ord (PatchMapWithMove k p)
48deriving instance (Ord k, Ord p, Ord (PatchTarget p)) => Ord (PatchMapWithMove k p)
38
49
@@ -67,11 +78,11 @@ deriving instance (Ord k, Ord p, Ord (PatchTarget p)) => Ord (From k p)
67data To k p
78data To k p
68 = To_NonMove
79 = To_NonMove
69 | To_Move !k !p
80 | To_Move !k !p
81+ deriving ( Show, Read, Eq, Ord
82+ , Functor, Foldable, Traversable
83+ )
70
84
71−deriving instance (Show k, Show p, Show (PatchTarget p)) => Show (To k p)
85+makeWrapped ''PatchMapWithMove
72−deriving instance (Read k, Read p, Read (PatchTarget p)) => Read (To k p)
73−deriving instance (Eq k, Eq p, Eq (PatchTarget p)) => Eq (To k p)
74−deriving instance (Ord k, Ord p, Ord (PatchTarget p)) => Ord (To k p)
75
86
76-- | Create a 'PatchMapWithMove', validating it
87-- | Create a 'PatchMapWithMove', validating it
77patchMapWithMove
88patchMapWithMove
@@ -94,12 +105,7 @@ patchMapWithMoveInsertAll m = PatchMapWithMove $ flip fmap m $ \v -> NodeInfo
94 , _nodeInfo_to = To_NonMove
105 , _nodeInfo_to = To_NonMove
95 }
106 }
96
107
97−-- | Extract the internal representation of the 'PatchMapWithMove'
98−unPatchMapWithMove
99− :: PatchMapWithMove k p -> Map k (NodeInfo k p)
100−unPatchMapWithMove (PatchMapWithMove p) = p
101−
102−-- | Make a @'PatchMapWithMove' k p@ which has the effect of inserting or updating a value @v@ to the given key @k@, like 'Map.insert'.
108+-- | Make a @'PatchMapWithMove' k p@ which has the effect of inserting or replacing a value @v@ at the given key @k@, like 'Map.insert'.
103insertMapKey
109insertMapKey
104 :: k -> PatchTarget p -> PatchMapWithMove k p
110 :: k -> PatchTarget p -> PatchMapWithMove k p
105insertMapKey k v = PatchMapWithMove . Map.singleton k $ NodeInfo (From_Insert v) To_NonMove
111insertMapKey k v = PatchMapWithMove . Map.singleton k $ NodeInfo (From_Insert v) To_NonMove