on develop help sign in
Merge branch 'develop' into patch-map-inner-patch-desugar
cfcd1cfJohn Ericson
ChangeLog.md+3−1
@@ -1,9 +1,11 @@
1# Revision history for patch
1# Revision history for patch
2
2
3−## Unreleased
3+## 0.0.3.0
4
4
5* Create `PatchMapWithPatchingMove` variant which supports moves with a patch.
5* Create `PatchMapWithPatchingMove` variant which supports moves with a patch.
6
6
7+* Create `DecidablyEmpty` subclass of `Monoid`.
8+
7## 0.0.2.0
9## 0.0.2.0
8
10
9* Consistently provide:
11* Consistently provide:
patch.cabal+1−1
@@ -1,5 +1,5 @@
1Name: patch
1Name: patch
2−Version: 0.0.2.0
2+Version: 0.0.3.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
src/Data/Monoid/DecidablyEmpty.hs+103−2
@@ -1,14 +1,115 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE DefaultSignatures #-}
2{-# LANGUAGE DefaultSignatures #-}
3+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+{-# LANGUAGE StandaloneDeriving #-}
5+{-# LANGUAGE TypeOperators #-}
2
6
3-- TODO upstream somwhere else?
7-- TODO upstream somwhere else?
4module Data.Monoid.DecidablyEmpty where
8module Data.Monoid.DecidablyEmpty where
5
9
10+import Data.Functor.Identity
11+import Data.Functor.Const
12+import Data.Monoid
13+import Data.Maybe (isNothing)
14+#if MIN_VERSION_base(4,11,0)
15+import Data.Ord
16+#endif
6import Data.Proxy
17import Data.Proxy
18+import Data.Semigroup hiding (First, Last)
19+#if MIN_VERSION_base(4,12,0)
20+import GHC.Generics
21+#endif
7
22
23+import qualified Data.IntSet as IntSet
24+import qualified Data.IntMap as IntMap
25+import qualified Data.Map as Map
26+import qualified Data.Sequence as Seq
27+import qualified Data.Set as Set
28+
29+import Data.GADT.Compare
30+import qualified Data.Dependent.Map as DMap
31+
32+-- | A 'DecidablyEmpty' is one where it can be computed whether or not an
33+-- arbitrary value is 'mempty'.
34+--
35+-- By using this class rather than 'Eq', we avoid unnecessary constraining the
36+-- contents of 'Functor's. This makes it possible to efficiently combine and/or
37+-- nest patch maps with 'Eq'-lacking values (e.g. functions) at the leaves.
8class Monoid a => DecidablyEmpty a where
38class Monoid a => DecidablyEmpty a where
9 isEmpty :: a -> Bool
39 isEmpty :: a -> Bool
10 default isEmpty :: Eq a => a -> Bool
40 default isEmpty :: Eq a => a -> Bool
11 isEmpty = (==) mempty
41 isEmpty = (==) mempty
12
42
43+-- base
44+
45+instance DecidablyEmpty Ordering
13−instance DecidablyEmpty (Proxy a) where
46+instance DecidablyEmpty ()
47+instance DecidablyEmpty Any
48+instance DecidablyEmpty All
49+-- instance DecidablyEmpty Lifetime
50+-- instance DecidablyEmpty Event
51+instance DecidablyEmpty [a] where
52+ isEmpty = null
53+instance
54+#if MIN_VERSION_base(4,11,0)
55+ Semigroup a
56+#else
57+ Monoid a
58+#endif
59+ => DecidablyEmpty (Maybe a) where
14− isEmpty ~Proxy = True
60+ isEmpty = isNothing
61+deriving instance (Num a, DecidablyEmpty a) => DecidablyEmpty (Product a)
62+deriving instance (DecidablyEmpty a, Num a) => DecidablyEmpty (Sum a)
63+deriving instance DecidablyEmpty a => DecidablyEmpty (Dual a)
64+instance DecidablyEmpty (First a) where
65+ isEmpty (First a) = isNothing a
66+instance DecidablyEmpty (Last a) where
67+ isEmpty (Last a) = isNothing a
68+deriving instance DecidablyEmpty a => DecidablyEmpty (Identity a)
69+instance Semigroup a => DecidablyEmpty (Option a) where
70+ isEmpty (Option a) = isNothing a
71+deriving instance DecidablyEmpty m => DecidablyEmpty (WrappedMonoid m)
72+instance (Ord a, Bounded a) => DecidablyEmpty (Max a)
73+instance (Ord a, Bounded a) => DecidablyEmpty (Min a)
74+instance DecidablyEmpty (Proxy s)
75+deriving instance DecidablyEmpty a => DecidablyEmpty (Const a b)
76+#if MIN_VERSION_base(4,11,0)
77+deriving instance DecidablyEmpty a => DecidablyEmpty (Down a)
78+#endif
79+#if MIN_VERSION_base(4,12,0)
80+deriving instance DecidablyEmpty p => DecidablyEmpty (Par1 p)
81+instance DecidablyEmpty (U1 p)
82+deriving instance DecidablyEmpty (f p) => DecidablyEmpty (Rec1 f p)
83+deriving instance DecidablyEmpty (f p) => DecidablyEmpty (M1 i c f p)
84+deriving instance DecidablyEmpty c => DecidablyEmpty (K1 i c p)
85+instance (DecidablyEmpty (f p), DecidablyEmpty (g p)) => DecidablyEmpty ((f :*: g) p) where
86+ isEmpty (x :*: y) = isEmpty x && isEmpty y
87+deriving instance DecidablyEmpty (f (g p)) => DecidablyEmpty ((f :.: g) p)
88+#endif
89+
90+instance (DecidablyEmpty a, DecidablyEmpty b) => DecidablyEmpty (a, b) where
91+ isEmpty (a, b) = isEmpty a && isEmpty b
92+instance (DecidablyEmpty a, DecidablyEmpty b, DecidablyEmpty c) => DecidablyEmpty (a, b, c) where
93+ isEmpty (a, b, c) = isEmpty a && isEmpty b && isEmpty c
94+instance (DecidablyEmpty a, DecidablyEmpty b, DecidablyEmpty c, DecidablyEmpty d) => DecidablyEmpty (a, b, c, d) where
95+ isEmpty (a, b, c, d) = isEmpty a && isEmpty b && isEmpty c && isEmpty d
96+instance (DecidablyEmpty a, DecidablyEmpty b, DecidablyEmpty c, DecidablyEmpty d, DecidablyEmpty e) => DecidablyEmpty (a, b, c, d, e) where
97+ isEmpty (a, b, c, d, e) = isEmpty a && isEmpty b && isEmpty c && isEmpty d && isEmpty e
98+
99+-- containers
100+
101+instance DecidablyEmpty IntSet.IntSet where
102+ isEmpty = IntSet.null
103+instance DecidablyEmpty (IntMap.IntMap v) where
104+ isEmpty = IntMap.null
105+instance Ord k => DecidablyEmpty (Map.Map k v) where
106+ isEmpty = Map.null
107+instance DecidablyEmpty (Seq.Seq v) where
108+ isEmpty = Seq.null
109+instance Ord k => DecidablyEmpty (Set.Set k) where
110+ isEmpty = Set.null
111+
112+-- dependent-map
113+
114+instance GCompare k => DecidablyEmpty (DMap.DMap k v) where
115+ isEmpty = DMap.null
src/Data/Patch.hs+1−1
@@ -18,7 +18,7 @@ import Data.Functor.Const (Const (..))
18import Data.Functor.Identity
18import Data.Functor.Identity
19import Data.Map.Monoidal (MonoidalMap)
19import Data.Map.Monoidal (MonoidalMap)
20import Data.Proxy
20import Data.Proxy
21−#if !MIN_VERSION_base(4,10,0)
21+#if !MIN_VERSION_base(4,11,0)
22import Data.Semigroup (Semigroup (..))
22import Data.Semigroup (Semigroup (..))
23#endif
23#endif
24import GHC.Generics
24import GHC.Generics
src/Data/Patch/Class.hs+3
@@ -1,10 +1,13 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE TypeFamilies #-}
2{-# LANGUAGE TypeFamilies #-}
2-- | The interface for types which represent changes made to other types
3-- | The interface for types which represent changes made to other types
3module Data.Patch.Class where
4module Data.Patch.Class where
4
5
5import Data.Functor.Identity
6import Data.Functor.Identity
6import Data.Maybe
7import Data.Maybe
8+#if !MIN_VERSION_base(4,11,0)
7import Data.Semigroup (Semigroup(..))
9import Data.Semigroup (Semigroup(..))
10+#endif
8import Data.Proxy
11import Data.Proxy
9
12
10-- | A 'Patch' type represents a kind of change made to a datastructure.
13-- | A 'Patch' type represents a kind of change made to a datastructure.
src/Data/Patch/DMap.hs+9
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE LambdaCase #-}
3{-# LANGUAGE LambdaCase #-}
3{-# LANGUAGE PolyKinds #-}
4{-# LANGUAGE PolyKinds #-}
@@ -5,6 +6,7 @@
5{-# LANGUAGE ScopedTypeVariables #-}
6{-# LANGUAGE ScopedTypeVariables #-}
6{-# LANGUAGE StandaloneDeriving #-}
7{-# LANGUAGE StandaloneDeriving #-}
7{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE TypeFamilies #-}
9+
8-- | 'Patch'es on 'DMap' that consist only of insertions (or overwrites) and deletions.
10-- | 'Patch'es on 'DMap' that consist only of insertions (or overwrites) and deletions.
9module Data.Patch.DMap where
11module Data.Patch.DMap where
10
12
@@ -18,7 +20,10 @@ import Data.Functor.Constant
18import Data.Functor.Misc
20import Data.Functor.Misc
19import qualified Data.IntMap as IntMap
21import qualified Data.IntMap as IntMap
20import qualified Data.Map as Map
22import qualified Data.Map as Map
23+import Data.Monoid.DecidablyEmpty
24+#if !MIN_VERSION_base(4,11,0)
21import Data.Semigroup (Semigroup (..))
25import Data.Semigroup (Semigroup (..))
26+#endif
22import Data.Some (Some)
27import Data.Some (Some)
23
28
24-- | A set of changes to a 'DMap'. Any element may be inserted/updated or deleted.
29-- | A set of changes to a 'DMap'. Any element may be inserted/updated or deleted.
@@ -30,6 +35,10 @@ deriving instance GCompare k => Semigroup (PatchDMap k v)
30
35
31deriving instance GCompare k => Monoid (PatchDMap k v)
36deriving instance GCompare k => Monoid (PatchDMap k v)
32
37
38+-- It won't let me derive for some reason
39+instance GCompare k => DecidablyEmpty (PatchDMap k v) where
40+ isEmpty (PatchDMap m) = DMap.null m
41+
33-- | Apply the insertions or deletions to a given 'DMap'.
42-- | Apply the insertions or deletions to a given 'DMap'.
34instance GCompare k => Patch (PatchDMap k v) where
43instance GCompare k => Patch (PatchDMap k v) where
35 type PatchTarget (PatchDMap k v) = DMap k v
44 type PatchTarget (PatchDMap k v) = DMap k v
src/Data/Patch/DMapWithMove.hs+8−1
@@ -29,7 +29,10 @@ import Data.GADT.Compare (GEq (..))
29import Data.GADT.Show (GShow, gshow)
29import Data.GADT.Show (GShow, gshow)
30import qualified Data.Map as Map
30import qualified Data.Map as Map
31import Data.Maybe
31import Data.Maybe
32+import Data.Monoid.DecidablyEmpty
33+#if !MIN_VERSION_base(4,11,0)
32−import Data.Semigroup (Semigroup (..), (<>))
34+import Data.Semigroup (Semigroup (..))
35+#endif
33import Data.Some (Some(Some))
36import Data.Some (Some(Some))
34import Data.These
37import Data.These
35
38
@@ -42,6 +45,10 @@ import Data.These
42-- * A move should always be represented with both the destination key (as a 'From_Move') and the source key (as a @'ComposeMaybe' ('Just' destination)@)
45-- * A move should always be represented with both the destination key (as a 'From_Move') and the source key (as a @'ComposeMaybe' ('Just' destination)@)
43newtype PatchDMapWithMove k v = PatchDMapWithMove (DMap k (NodeInfo k v))
46newtype PatchDMapWithMove k v = PatchDMapWithMove (DMap k (NodeInfo k v))
44
47
48+-- It won't let me derive for some reason
49+instance GCompare k => DecidablyEmpty (PatchDMapWithMove k v) where
50+ isEmpty (PatchDMapWithMove m) = DMap.null m
51+
45-- |Structure which represents what changes apply to a particular key. @_nodeInfo_from@ specifies what happens to this key, and in particular what other key
52-- |Structure which represents what changes apply to a particular key. @_nodeInfo_from@ specifies what happens to this key, and in particular what other key
46-- the current key is moving from, while @_nodeInfo_to@ specifies what key the current key is moving to if involved in a move.
53-- the current key is moving from, while @_nodeInfo_to@ specifies what key the current key is moving to if involved in a move.
47data NodeInfo k v a = NodeInfo
54data NodeInfo k v a = NodeInfo
src/Data/Patch/IntMap.hs+9−6
@@ -1,7 +1,9 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE DeriveTraversable #-}
2{-# LANGUAGE DeriveTraversable #-}
2{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE MultiParamTypeClasses #-}
5{-# LANGUAGE MultiParamTypeClasses #-}
6+{-# LANGUAGE StandaloneDeriving #-}
5{-# LANGUAGE TemplateHaskell #-}
7{-# LANGUAGE TemplateHaskell #-}
6{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE TypeFamilies #-}
7
9
@@ -13,7 +15,10 @@ import Control.Lens
13import Data.IntMap.Strict (IntMap)
15import Data.IntMap.Strict (IntMap)
14import qualified Data.IntMap.Strict as IntMap
16import qualified Data.IntMap.Strict as IntMap
15import Data.Maybe
17import Data.Maybe
16−import Data.Semigroup
18+import Data.Monoid.DecidablyEmpty
19+#if !MIN_VERSION_base(4,11,0)
20+import Data.Semigroup (Semigroup (..))
21+#endif
17import Data.Patch.Class
22import Data.Patch.Class
18
23
19-- | 'Patch' for 'IntMap' which represents insertion or deletion of keys in the mapping.
24-- | 'Patch' for 'IntMap' which represents insertion or deletion of keys in the mapping.
@@ -21,16 +26,14 @@ import Data.Patch.Class
21-- and @Nothing@ means delete.
26-- and @Nothing@ means delete.
22newtype PatchIntMap a = PatchIntMap { unPatchIntMap :: IntMap (Maybe a) }
27newtype PatchIntMap a = PatchIntMap { unPatchIntMap :: IntMap (Maybe a) }
23 deriving ( Show, Read, Eq, Ord
28 deriving ( Show, Read, Eq, Ord
24− , Functor, Foldable, Traversable, Monoid
29+ , Functor, Foldable, Traversable
30+ , Monoid, DecidablyEmpty
25 )
31 )
26
32
27-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
33-- | @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
34-- If the same key is modified by both patches, the one on the left will take
29-- precedence.
35-- precedence.
30−instance Semigroup (PatchIntMap v) where
36+deriving instance Semigroup (PatchIntMap v)
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
37
35makeWrapped ''PatchIntMap
38makeWrapped ''PatchIntMap
36
39
src/Data/Patch/Map.hs+9−8
@@ -1,5 +1,7 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE DeriveTraversable #-}
2{-# LANGUAGE DeriveTraversable #-}
2{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE LambdaCase #-}
5{-# LANGUAGE LambdaCase #-}
4{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
5{-# LANGUAGE StandaloneDeriving #-}
7{-# LANGUAGE StandaloneDeriving #-}
@@ -16,7 +18,8 @@ import Control.Lens
16import Data.Map (Map)
18import Data.Map (Map)
17import qualified Data.Map as Map
19import qualified Data.Map as Map
18import Data.Maybe
20import Data.Maybe
19−import Data.Semigroup
21+import Data.Monoid.DecidablyEmpty
22+import Data.Semigroup (Semigroup (..), stimesIdempotentMonoid)
20
23
21-- | A set of changes to a 'Map'. Any element may be inserted/updated or
24-- | A set of changes to a 'Map'. Any element may be inserted/updated or
22-- deleted. Insertions are represented as values wrapped in 'Just', while
25-- deleted. Insertions are represented as values wrapped in 'Just', while
@@ -24,11 +27,14 @@ import Data.Semigroup
24newtype PatchMap k v = PatchMap { unPatchMap :: Map k (Maybe v) }
27newtype PatchMap k v = PatchMap { unPatchMap :: Map k (Maybe v) }
25 deriving ( Show, Read, Eq, Ord
28 deriving ( Show, Read, Eq, Ord
26 , Foldable, Traversable
29 , Foldable, Traversable
30+ , DecidablyEmpty
27 )
31 )
28
32
29-- | 'fmap'ping a 'PatchMap' will alter all of the values it will insert.
33-- | 'fmap'ping a 'PatchMap' will alter all of the values it will insert.
30-- Deletions are unaffected.
34-- Deletions are unaffected.
31deriving instance Functor (PatchMap k)
35deriving instance Functor (PatchMap k)
36+-- | The empty 'PatchMap' contains no insertions or deletions
37+deriving instance Ord k => Monoid (PatchMap k v)
32
38
33-- | @a <> b@ will apply the changes of @b@ and then apply the changes of @a@.
39-- | @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
40-- If the same key is modified by both patches, the one on the left will take
@@ -38,8 +44,6 @@ instance Ord k => Semigroup (PatchMap k v) where
38 -- PatchMap is idempotent, so stimes n is id for every n
44 -- PatchMap is idempotent, so stimes n is id for every n
39 stimes = stimesIdempotentMonoid
45 stimes = stimesIdempotentMonoid
40
46
41−makeWrapped ''PatchMap
42−
43-- | Apply the insertions or deletions to a given 'Map'.
47-- | Apply the insertions or deletions to a given 'Map'.
44instance Ord k => Patch (PatchMap k v) where
48instance Ord k => Patch (PatchMap k v) where
45 type PatchTarget (PatchMap k v) = Map k v
49 type PatchTarget (PatchMap k v) = Map k v
@@ -57,11 +61,6 @@ instance TraversableWithIndex k (PatchMap k) where
57 itraverse = itraversed . Indexed
61 itraverse = itraversed . Indexed
58 itraversed = _Wrapped .> itraversed <. traversed
62 itraversed = _Wrapped .> itraversed <. traversed
59
63
60−-- | The empty 'PatchMap' contains no insertions or deletions
61−instance Ord k => Monoid (PatchMap k v) where
62− mempty = PatchMap mempty
63− mappend = (<>)
64−
65-- | Returns all the new elements that will be added to the 'Map'
64-- | Returns all the new elements that will be added to the 'Map'
66patchMapNewElements :: PatchMap k v -> [v]
65patchMapNewElements :: PatchMap k v -> [v]
67patchMapNewElements (PatchMap p) = catMaybes $ Map.elems p
66patchMapNewElements (PatchMap p) = catMaybes $ Map.elems p
@@ -69,3 +68,5 @@ patchMapNewElements (PatchMap p) = catMaybes $ Map.elems p
69-- | Returns all the new elements that will be added to the 'Map'
68-- | Returns all the new elements that will be added to the 'Map'
70patchMapNewElementsMap :: PatchMap k v -> Map k v
69patchMapNewElementsMap :: PatchMap k v -> Map k v
71patchMapNewElementsMap (PatchMap p) = Map.mapMaybe id p
70patchMapNewElementsMap (PatchMap p) = Map.mapMaybe id p
71+
72+makeWrapped ''PatchMap
src/Data/Patch/MapWithMove.hs+1−1
@@ -34,7 +34,7 @@ import Data.List
34import Data.Map (Map)
34import Data.Map (Map)
35import qualified Data.Map as Map
35import qualified Data.Map as Map
36import Data.Proxy
36import Data.Proxy
37−#if !MIN_VERSION_base(4,10,0)
37+#if !MIN_VERSION_base(4,11,0)
38import Data.Semigroup (Semigroup (..))
38import Data.Semigroup (Semigroup (..))
39#endif
39#endif
40import Data.Traversable (foldMapDefault)
40import Data.Traversable (foldMapDefault)
src/Data/Patch/MapWithPatchingMove.hs+33−8
@@ -1,4 +1,5 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE LambdaCase #-}
5{-# LANGUAGE LambdaCase #-}
@@ -25,7 +26,7 @@ import Data.List
25import Data.Map (Map)
26import Data.Map (Map)
26import qualified Data.Map as Map
27import qualified Data.Map as Map
27import Data.Maybe
28import Data.Maybe
28−#if !MIN_VERSION_base(4,10,0)
29+#if !MIN_VERSION_base(4,11,0)
29import Data.Semigroup (Semigroup (..))
30import Data.Semigroup (Semigroup (..))
30#endif
31#endif
31import Data.Monoid.DecidablyEmpty
32import Data.Monoid.DecidablyEmpty
@@ -46,6 +47,14 @@ deriving instance (Ord k, Read k, Read p, Read (PatchTarget p)) => Read (PatchMa
46deriving instance (Eq k, Eq p, Eq (PatchTarget p)) => Eq (PatchMapWithPatchingMove k p)
47deriving instance (Eq k, Eq p, Eq (PatchTarget p)) => Eq (PatchMapWithPatchingMove k p)
47deriving instance (Ord k, Ord p, Ord (PatchTarget p)) => Ord (PatchMapWithPatchingMove k p)
48deriving instance (Ord k, Ord p, Ord (PatchTarget p)) => Ord (PatchMapWithPatchingMove k p)
48
49
50+deriving instance ( Ord k
51+#if !MIN_VERSION_base(4,11,0)
52+ , Semigroup p
53+#endif
54+ , DecidablyEmpty p
55+ , Patch p
56+ ) => DecidablyEmpty (PatchMapWithPatchingMove k p)
57+
49-- | Holds the information about each key: where its new value should come from,
58-- | Holds the information about each key: where its new value should come from,
50-- and where its old value should go to
59-- and where its old value should go to
51data NodeInfo k p = NodeInfo
60data NodeInfo k p = NodeInfo
@@ -127,7 +136,13 @@ insertMapKey k v = PatchMapWithPatchingMove . Map.singleton k $ NodeInfo (From_I
127-- 'Map.delete' src (maybe map ('Map.insert' dst) (Map.lookup src map))
136-- 'Map.delete' src (maybe map ('Map.insert' dst) (Map.lookup src map))
128-- @
137-- @
129moveMapKey
138moveMapKey
139+ :: ( DecidablyEmpty p
140+#if !MIN_VERSION_base(4,11,0)
141+ , Semigroup p
142+#endif
143+ , Patch p
144+ )
130− :: (DecidablyEmpty p, Patch p) => Ord k => k -> k -> PatchMapWithPatchingMove k p
145+ => Ord k => k -> k -> PatchMapWithPatchingMove k p
131moveMapKey src dst
146moveMapKey src dst
132 | src == dst = mempty
147 | src == dst = mempty
133 | otherwise =
148 | otherwise =
@@ -146,7 +161,12 @@ moveMapKey src dst
146-- . Map.delete a . Map.delete b $ map
161-- . Map.delete a . Map.delete b $ map
147-- @
162-- @
148swapMapKey
163swapMapKey
149− :: (DecidablyEmpty p, Patch p)
164+ :: ( DecidablyEmpty p
165+#if !MIN_VERSION_base(4,11,0)
166+ , Semigroup p
167+#endif
168+ , Patch p
169+ )
150 => Ord k => k -> k -> PatchMapWithPatchingMove k p
170 => Ord k => k -> k -> PatchMapWithPatchingMove k p
151swapMapKey src dst
171swapMapKey src dst
152 | src == dst = mempty
172 | src == dst = mempty
@@ -248,7 +268,7 @@ patchThatChangesMap oldByIndex newByIndex = patch
248 putRemainingKeys $ Set.delete k fromKs
268 putRemainingKeys $ Set.delete k fromKs
249 return $ NodeInfo (From_Move k mempty) $ Just undefined -- There's an existing value, and it's here, so no patch necessary
269 return $ NodeInfo (From_Move k mempty) $ Just undefined -- There's an existing value, and it's here, so no patch necessary
250 else do
270 else do
251− (fromK, remainingKeys) <- return . fromJust $ Set.minView fromKs -- There's an existing value, but it's not here; move it here
271+ (fromK, remainingKeys) <- return . fromMaybe (error "patchThatChangesMap: impossible: fromKs was empty") $ Set.minView fromKs -- There's an existing value, but it's not here; move it here
252 putRemainingKeys remainingKeys
272 putRemainingKeys remainingKeys
253 return $ NodeInfo (From_Move fromK mempty) $ Just undefined
273 return $ NodeInfo (From_Move fromK mempty) $ Just undefined
254 Map.traverseWithKey f newByIndex
274 Map.traverseWithKey f newByIndex
@@ -277,14 +297,17 @@ nodeInfoSetTo
277 :: To k -> NodeInfo k v -> NodeInfo k v
297 :: To k -> NodeInfo k v -> NodeInfo k v
278nodeInfoSetTo to ni = ni { _nodeInfo_to = to }
298nodeInfoSetTo to ni = ni { _nodeInfo_to = to }
279
299
280−-- |Helper data structure used for composing patches using the monoid instance.
300+-- | Helper data structure used for composing patches using the monoid instance.
281data Fixup k v
301data Fixup k v
282 = Fixup_Delete
302 = Fixup_Delete
283 | Fixup_Update (These (From k v) (To k))
303 | Fixup_Update (These (From k v) (To k))
284
304
285−-- |Compose patches having the same effect as applying the patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
305+-- | Compose patches having the same effect as applying the patches in turn:
306+-- @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
286instance ( Ord k
307instance ( Ord k
287− , Monoid p
308+#if !MIN_VERSION_base(4,11,0)
309+ , Semigroup p
310+#endif
288 , DecidablyEmpty p
311 , DecidablyEmpty p
289 , Patch p
312 , Patch p
290 ) => Semigroup (PatchMapWithPatchingMove k p) where
313 ) => Semigroup (PatchMapWithPatchingMove k p) where
@@ -343,7 +366,9 @@ instance ( Ord k
343-- | Compose patches having the same effect as applying the patches in turn:
366-- | Compose patches having the same effect as applying the patches in turn:
344-- @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
367-- @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
345instance ( Ord k
368instance ( Ord k
346− , Monoid p
369+#if !MIN_VERSION_base(4,11,0)
370+ , Semigroup p
371+#endif
347 , DecidablyEmpty p
372 , DecidablyEmpty p
348 , Patch p
373 , Patch p
349 ) => Monoid (PatchMapWithPatchingMove k p) where
374 ) => Monoid (PatchMapWithPatchingMove k p) where