on develop help sign in
Get everything type checking again
commit3f037af800e0f74cf70badd4255e3c2cd6913da5 authorJohn Ericson <git@JohnEricson.me> dateSat 11 Jan 2020, 19:23 (7 years ago) parent69a7ab8
4 files changed+307−285
src/Data/Functor/Misc.hs+28−5 src/Data/Patch/Class.hs+20−21 src/Data/Patch/DMapWithMove.hs+197−218 src/Data/Patch/MapWithMove.hs+62−41
src/Data/Functor/Misc.hs+28−5
@@ -1,6 +1,6 @@
11{-# LANGUAGE CPP #-}
22{-# LANGUAGE DeriveDataTypeable #-}
3−{-# LANGUAGE DeriveFunctor #-}
3+{-# LANGUAGE DeriveTraversable #-}
44{-# LANGUAGE FlexibleContexts #-}
55{-# LANGUAGE FlexibleInstances #-}
66{-# LANGUAGE GADTs #-}
@@ -17,6 +17,8 @@
1717module Data.Functor.Misc
1818 ( -- * Const2
1919 Const2 (..)
20+ , Proxy3 (..)
21+ , First2 (..)
2022 , unConst2
2123 , dmapToMap
2224 , dmapToIntMap
@@ -37,6 +39,7 @@ module Data.Functor.Misc
3739 , ComposeMaybe (..)
3840 ) where
3941
42+import qualified Control.Category as Cat
4043import Control.Applicative ((<$>))
4144import Data.Dependent.Map (DMap)
4245import qualified Data.Dependent.Map as DMap
@@ -48,6 +51,7 @@ import Data.IntMap (IntMap)
4851import qualified Data.IntMap as IntMap
4952import Data.Map (Map)
5053import qualified Data.Map as Map
54+import qualified Data.Semigroupoid as Cat
5155import Data.Some (Some(Some))
5256import Data.These
5357import Data.Type.Equality ((:~:)(Refl))
@@ -63,15 +67,15 @@ data Const2 :: * -> x -> x -> * where
6367 Const2 :: k -> Const2 k v v
6468 deriving (Typeable)
6569
66−-- | Extract the value from a Const2
67−unConst2 :: Const2 k v v' -> k
68−unConst2 (Const2 k) = k
69−
7070deriving instance Eq k => Eq (Const2 k v v')
7171deriving instance Ord k => Ord (Const2 k v v')
7272deriving instance Show k => Show (Const2 k v v')
7373deriving instance Read k => Read (Const2 k v v)
7474
75+-- | Extract the value from a Const2
76+unConst2 :: Const2 k v v' -> k
77+unConst2 (Const2 k) = k
78+
7579instance Show k => GShow (Const2 k v) where
7680 gshowsPrec n x@(Const2 _) = showsPrec n x
7781
@@ -87,6 +91,25 @@ instance Ord k => GCompare (Const2 k v) where
8791 EQ -> GEQ
8892 GT -> GGT
8993
94+data Proxy3 :: x -> y -> z -> * where
95+ Proxy3 :: Proxy3 vx vy vz
96+ deriving ( Show, Read, Eq, Ord
97+ , Functor, Foldable, Traversable
98+ , Typeable
99+ )
100+
101+instance Cat.Category (Proxy3 x) where
102+ id = Proxy3
103+ ~Proxy3 . ~Proxy3 = Proxy3
104+
105+newtype First2 (t :: k -> *) (a :: k) (b :: k) = First2 (t b)
106+ deriving ( Show, Read, Eq, Ord
107+ , Functor, Foldable, Traversable
108+ )
109+
110+instance Cat.Semigroupoid (First2 x) where
111+ First2 x `o` ~(First2 _) = First2 x
112+
90113-- | Convert a 'DMap' to a regular 'Map'
91114dmapToMap :: DMap (Const2 k v) Identity -> Map k v
92115dmapToMap = Map.fromDistinctAscList . map (\(Const2 k :=> Identity v) -> (k, v)) . DMap.toAscList
src/Data/Patch/Class.hs+20−21
@@ -1,5 +1,7 @@
11{-# LANGUAGE DefaultSignatures #-}
22{-# LANGUAGE DeriveTraversable #-}
3+{-# LANGUAGE DerivingStrategies #-}
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
35{-# LANGUAGE FlexibleInstances #-}
46{-# LANGUAGE MultiParamTypeClasses #-}
57{-# LANGUAGE PolyKinds #-}
@@ -8,7 +10,9 @@
810-- | The interface for types which represent changes made to other types
911module Data.Patch.Class where
1012
13+import qualified Data.Semigroupoid as Cat
1114import Data.Functor.Identity
15+import Data.Functor.Misc
1216import Data.Maybe
1317import Data.Semigroup (Semigroup(..))
1418import Data.Proxy
@@ -128,6 +132,7 @@ applyAlwaysHet2 p t = case applyHet2 p t of
128132
129133-- | Connect the classes without quanitified constraints
130134newtype ProjectLocal p from to = ProjectLocal { unProjectLocal :: p from to }
135+ deriving newtype Cat.Semigroupoid
131136
132137instance PatchHet2 p => PatchHet (ProjectLocal p from to) where
133138 type PatchSource (ProjectLocal p from to) = PatchSource1 p from
@@ -145,24 +150,18 @@ instance ( PatchHet2Base p
145150 , PatchSource1 p ~ PatchTarget1 p
146151 ) => Patch2 p
147152
148−newtype Replace2 (t :: k -> *) (a :: k) (b :: k) = Replace2 (t b)
149− deriving ( Show, Read, Eq, Ord
150− , Functor, Foldable, Traversable
151− )
152−
153−data Proxy2 t a b = Proxy2
154− deriving ( Show, Read, Eq, Ord
155− , Functor, Foldable, Traversable
156− )
157−
158−-- | 'Replace2' can be used as a 'Patch' that always fully replaces the value
159−instance PatchHet (Replace2 (t :: k -> *) (from :: k) (to :: k)) where
160− type PatchSource (Replace2 t from to) = t from
161− type PatchTarget (Replace2 t from to) = t to
162− applyHet (Replace2 val) _ = Right val
163−
164−-- | 'Proxy2' can be used as a 'Patch' that always does nothing
165−instance PatchHet (Proxy2 (t :: k -> *) (a :: k) (a :: k)) where
166− type PatchSource (Proxy2 t a a) = t a
167− type PatchTarget (Proxy2 t a a) = t a
168− applyHet ~Proxy2 _ = Left Refl
153+-- | 'First2' can be used as a 'Patch' that always fully replaces the value
154+instance PatchHet (First2 (t :: k -> *) (from :: k) (to :: k)) where
155+ type PatchSource (First2 t from to) = t from
156+ type PatchTarget (First2 t from to) = t to
157+ applyHet (First2 val) _ = Right val
158+
159+-- | 'Proxy3' can be used as a 'Patch' that always does nothing
160+instance PatchHet (Proxy3 (t :: k -> *) (a :: k) (a :: k)) where
161+ type PatchSource (Proxy3 t a a) = t a
162+ type PatchTarget (Proxy3 t a a) = t a
163+ applyHet ~Proxy3 _ = Left Refl
164+
165+instance PatchHet2Base (Proxy3 (t :: k -> *) :: k -> k -> *) where
166+ type PatchSource1 (Proxy3 t) = t
167+ type PatchTarget1 (Proxy3 t) = t
src/Data/Patch/DMapWithMove.hs+197−218
@@ -21,40 +21,36 @@
2121module Data.Patch.DMapWithMove where
2222
2323import qualified Control.Category as Cat
24−import Data.Constraint.Extras
25−import Data.Constraint.Compose
26−import Data.Dependent.Map (DMap, DSum (..), GCompare (..))
24+--import qualified Control.Category.DecidablyEmpty as Cat
25+import Data.Constraint.Extras (Has')
26+import Data.Dependent.Map (DMap)
27+import Data.Dependent.Sum (DSum (..))
2728import qualified Data.Dependent.Map as DMap
28−import Data.Functor.Constant
29+import Data.Functor.Constant (Constant (..))
2930import Data.Functor.Misc
30−import Data.Functor.Product
31−import Data.GADT.Compare (GEq (..), GCompare)
31+ ( Const2 (..), Proxy3 (..)
32+ , weakenDMapWith
33+ , dmapToMapWith
34+ )
35+import Data.Functor.Product (Product (..))
36+import Data.GADT.Compare (GEq (..), GCompare (..))
3237import Data.GADT.Show (GRead, GShow, gshow)
3338import qualified Data.Map as Map
3439import Data.Maybe
35−import Data.Monoid.DecidablyEmpty
3640import Data.Semigroup (Semigroup (..), (<>))
3741import Data.Semigroupoid as Cat
3842import Data.Some (Some(Some))
39−import Data.Proxy
40−import Data.These
41−import Data.Type.Equality ((:~:) (..))
42−import Data.Kind (Constraint)
43+import Data.Proxy (Proxy (..))
44+import Data.These (These (..))
4345
4446import Data.Patch.Class
47+ ( Patch (..), PatchHet (..)
48+ , PatchHet2 (..), PatchSource1, PatchTarget1
49+ , applyAlwaysHet2
50+ )
4551import Data.Patch.MapWithMove (PatchMapWithMove (..))
4652import qualified Data.Patch.MapWithMove as MapWithMove
4753
48−-- | Composition for constraints.
49−class p (f a a) => DupC (p :: k2 -> Constraint) (f :: k1 -> k1 -> k2) (a :: k1)
50−instance p (f a a) => DupC p f a
51−
52−type ConstraintsForZip f (c :: k -> Constraint) (g :: k' -> k' -> k) =
53− ConstraintsFor f (DupC c g)
54−
55−type HasZip (c :: k -> Constraint) f (g :: k' -> k' -> k) =
56− (ArgDict (DupC c g) f, ConstraintsForZip f c g)
57−
5854-- | Like 'PatchMapWithMove', but for 'DMap'. Each key carries a 'NodeInfo'
5955-- which describes how it will be changed by the patch and connects move sources
6056-- and destinations.
@@ -68,22 +64,22 @@ type HasZip (c :: k -> Constraint) f (g :: k' -> k' -> k) =
6864-- destination)@)
6965newtype PatchDMapWithMove k v = PatchDMapWithMove (DMap k (NodeInfo k v))
7066
71−deriving instance ( GShow k
72− , HasZip Show k p
73− , Has' Show k (PatchTarget1 p)
74− ) => Show (PatchDMapWithMove k p)
75−deriving instance ( GRead k
76− , HasZip Read k p
77− , Has' Read k (PatchTarget1 p)
78− ) => Read (PatchDMapWithMove k p)
79−deriving instance ( GEq k
80− , HasZip Eq k p
81− , Has' Eq k (PatchTarget1 p)
82− ) => Eq (PatchDMapWithMove k p)
83−deriving instance ( GCompare k
84− , HasZip Ord k p
85− , Has' Ord k (PatchTarget1 p)
86− ) => Ord (PatchDMapWithMove k p)
67+--deriving instance ( GShow k
68+-- , HasZip Show k p
69+-- , Has' Show k (PatchTarget1 p)
70+-- ) => Show (PatchDMapWithMove k p)
71+--deriving instance ( GRead k
72+-- , HasZip Read k p
73+-- , Has' Read k (PatchTarget1 p)
74+-- ) => Read (PatchDMapWithMove k p)
75+--deriving instance ( GEq k
76+-- , HasZip Eq k p
77+-- , Has' Eq k (PatchTarget1 p)
78+-- ) => Eq (PatchDMapWithMove k p)
79+--deriving instance ( GCompare k
80+-- , HasZip Ord k p
81+-- , Has' Ord k (PatchTarget1 p)
82+-- ) => Ord (PatchDMapWithMove k p)
8783
8884-- | Structure which represents what changes apply to a particular key.
8985-- @_nodeInfo_from@ specifies what happens to this key, and in particular what
@@ -97,91 +93,22 @@ data NodeInfo k p a = NodeInfo
9793 -- @ComposeMaybe (Just k)@ when there is a corresponding 'From_Move'.
9894 }
9995
100−deriving instance ( Show (k a)
101− , Show (p a a)
102− , Show (PatchTarget1 p a)
103− ) => Show (NodeInfo k p a)
104−deriving instance ( Read (k a)
105− , Read (p a a)
106− , Read (PatchTarget1 p a)
107− ) => Read (NodeInfo k p a)
108−deriving instance ( Eq (k a)
109− , Eq (p a a)
110− , Eq (PatchTarget1 p a)
111− ) => Eq (NodeInfo k p a)
112−deriving instance ( Ord (k a)
113− , Ord (p a a)
114− , Ord (PatchTarget1 p a)
115− ) => Ord (NodeInfo k p a)
116−
117−-- | Structure describing a particular change to a key, be it inserting a new
118−-- key (@By_Insert@), updating an existing key (@By_Insert@ again), deleting
119−-- a key (@By_Delete@), or moving a key (@By_Move@).
120−--
121−-- This type isn't used directly as the from field patch, but is instead wrapped
122−-- in an existential. However, it is nice to be able to reason about this in
123−-- isolation as it is itself a @Semigroupoid@ when the underlying patch is.
124−data By (k :: a -> *) (p :: a -> a -> *) :: a -> a -> * where
125− -- | Insert a new or update an existing key with the given value @PatchTarget1
126− -- p a@
127− By_Insert :: PatchTarget1 p to -> By k p from to
128− -- | Delete the existing key
129− By_Delete :: By k p from to
130− -- | Move the value from the given key @k a@ to this key. The source key
131− -- should also have an entry in the patch giving the current key as
132− -- @_nodeInfo_to@, usually but not necessarily with @By_Delete@.
133− By_Move :: !(k from) -> p from to -> By k p from to
134−
135−deriving instance ( Show (k to)
136− , Show (p from to)
137− , Show (PatchTarget1 p to)
138− ) => Show (By k p from to)
139−deriving instance ( Read (k to)
140− , Read (p from to)
141− , Read (PatchTarget1 p to)
142− ) => Read (By k p from to)
143−deriving instance ( Eq (k to)
144− , Eq (p from to)
145− , Eq (PatchTarget1 p to)
146− ) => Eq (By k p from to)
147−deriving instance ( Ord (k to)
148− , Ord (p from to)
149− , Ord (PatchTarget1 p to)
150− ) => Ord (By k p from to)
151−
152−mapByPatch
153− :: PatchTarget1 p0 ~ PatchTarget1 p1
154− => ((p0 from to) -> (p1 from to))
155− -> By k p0 from to
156− -> By k p1 from to
157−mapByPatch f = \case
158− By_Insert v -> By_Insert v
159− By_Delete -> By_Delete
160− By_Move k p -> By_Move k $ f p
161−
162−-- | Compose patches having the same effect as applying the patches in turn:
163−-- @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
164−instance ( PatchSource1 p ~ PatchTarget1 p
165− , Cat.Semigroupoid p
166− , PatchHet2 p
167− ) => Cat.Semigroupoid (By k p) where
168− o p0 p1 = mapByPatch unProjectLocal $
169− oLocal (mapByPatch ProjectLocal p0) (mapByPatch ProjectLocal p1)
170−
171−oLocal
172− :: ( PatchSource1 p ~ PatchTarget1 p
173− , PatchHet2Locally p between after
174− )
175− => By k p between after
176− -> By k p before between
177− -> By k p before after
178−By_Insert new `oLocal` _ = By_Insert new
179−By_Delete `oLocal` _ = By_Delete
180−By_Move _ x `oLocal` By_Insert y = By_Insert $ applyAlwaysHet2 x y
181−By_Move _ x `oLocal` By_Move src y = By_Move src $ x `o` y
182−By_Move _ _ `oLocal` By_Delete = By_Delete
183−
184−newtype Flip p to from = Flip (p from to)
96+--deriving instance ( Show (k a)
97+-- , Show (p a a)
98+-- , Show (PatchTarget1 p a)
99+-- ) => Show (NodeInfo k p a)
100+--deriving instance ( Read (k a)
101+-- , Read (p a a)
102+-- , Read (PatchTarget1 p a)
103+-- ) => Read (NodeInfo k p a)
104+--deriving instance ( Eq (k a)
105+-- , Eq (p a a)
106+-- , Eq (PatchTarget1 p a)
107+-- ) => Eq (NodeInfo k p a)
108+--deriving instance ( Ord (k a)
109+-- , Ord (p a a)
110+-- , Ord (PatchTarget1 p a)
111+-- ) => Ord (NodeInfo k p a)
185112
186113-- | Structure describing a particular change to a key, be it inserting a new
187114-- key (@From_Insert@), updating an existing key (@From_Insert@ again), deleting
@@ -201,25 +128,30 @@ data From (k :: a -> *) (p :: a -> a -> *) :: a -> * where
201128 -- @_nodeInfo_to@, usually but not necessarily with @From_Delete@.
202129 From_Move :: !(DSum k (Flip p to)) -> From k p to
203130
204−deriving instance ( Show (k a)
205− , Show (p a a)
131+deriving instance ( Show (k a), GShow k
132+ , Has' Show k (Flip p a)
206133 , Show (PatchTarget1 p a)
207134 ) => Show (From k p a)
208−deriving instance ( Read (k a)
209− , Read (p a a)
135+deriving instance ( Read (k a), GRead k
136+ , Has' Read k (Flip p a)
210137 , Read (PatchTarget1 p a)
211138 ) => Read (From k p a)
212−
213139deriving instance ( GEq k
214− , HasZip Eq k p
140+ , Has' Eq k (Flip p a)
215141 , Eq (PatchTarget1 p a)
216142 ) => Eq (From k p a)
217−
218143deriving instance ( GCompare k
219− , HasZip Ord k p
144+ , Has' Eq k (Flip p a) -- superclass bug
145+ , Has' Ord k (Flip p a)
220146 , Ord (PatchTarget1 p a)
221147 ) => Ord (From k p a)
222148
149+newtype Flip p to from = Flip (p from to)
150+
151+instance Cat.Category p => Cat.Category (Flip (p :: k -> k -> *)) where
152+ id = Flip Cat.id
153+ Flip y . Flip x = Flip $ x Cat.. y
154+
223155-- | The "to" part of a 'NodeInfo'. Rather than be built out of @From@ like @From@
224156-- is, we store just the information necessary to compose a @To@ and @From@ like
225157-- @oLocal@ composes two @From@s.
@@ -231,38 +163,24 @@ data To (k :: a -> *) (p :: a -> a -> *) :: a -> * where
231163 -- @_nodeInfo_from@, usually but not necessarily with @To_Delete@.
232164 To_Move :: !(DSum k (p from)) -> To k p from
233165
234−deriving instance ( Show (k a)
235− , Show (p a a)
166+deriving instance ( Show (k a), GShow k
167+ , Has' Show k (p a)
236168 , Show (PatchTarget1 p a)
237169 ) => Show (To k p a)
238−deriving instance ( Read (k a)
239− , Read (p a a)
170+deriving instance ( Read (k a), GRead k
171+ , Has' Read k (p a)
240172 , Read (PatchTarget1 p a)
241173 ) => Read (To k p a)
242−
243174deriving instance ( GEq k
244− , HasZip Eq k p
175+ , Has' Eq k (p a)
245176 , Eq (PatchTarget1 p a)
246177 ) => Eq (To k p a)
247−
248178deriving instance ( GCompare k
249− , HasZip Ord k p
179+ , Has' Eq k (p a) -- superclass bug
180+ , Has' Ord k (p a)
250181 , Ord (PatchTarget1 p a)
251182 ) => Ord (To k p a)
252183
253−--oToFrom
254−-- :: ( PatchSource1 p ~ PatchTarget1 p
255−-- , PatchHet2 p
256−-- )
257−-- => To k p between
258−-- -> From k p between
259−-- -> DSum k (From k p)
260−--From_Insert new `oToFrom` _ = From_Insert new
261−--From_Delete `oToFrom` _ = From_Delete
262−--From_Move _ x `oToFrom` From_Insert y = From_Insert $ applyAlwaysHet2 x y
263−--From_Move _ x `oToFrom` From_Move src y = From_Move src $ x `o` y
264−--From_Move _ _ `oToFrom` From_Delete = From_Delete
265−
266184-- |Test whether a 'PatchDMapWithMove' satisfies its invariants.
267185validPatchDMapWithMove
268186 :: forall k v
@@ -320,7 +238,7 @@ data Fixup k p a
320238-- @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
321239instance ( GCompare k
322240 , Cat.Semigroupoid p
323− -- , DecidablyEmpty p
241+ -- , Cat.DecidablyEmpty p
324242 , PatchHet2 p
325243 , PatchSource1 p ~ PatchTarget1 p
326244 ) => Semigroup (PatchDMapWithMove k p) where
@@ -332,12 +250,12 @@ instance ( GCompare k
332250 ma
333251 mb
334252 h :: DSum k (Pair1 (To k p) (From k p)) -> [DSum k (Fixup k p)]
335− h ((between :: k between) :=> Pair1 editAfter editBefore) = case (editAfter, editBefore) of
253+ h ((_ :: k between) :=> Pair1 editAfter editBefore) = case (editAfter, editBefore) of
336254 (To_Move ((toAfter :: k after) :=> p1), From_Move ((fromBefore :: k before) :=> Flip p0)) ->
337− case toAfter `geq` fromBefore of
338− Just Refl | isNull p0 ->
339− [ toAfter :=> Fixup_Delete ]
340− _ ->
255+ --case toAfter `geq` fromBefore of
256+ -- Just Refl | Just Refl <- Cat.isId p0 ->
257+ -- [ toAfter :=> Fixup_Delete ]
258+ -- _ ->
341259 [ toAfter :=> Fixup_Update (This $ From_Move $ fromBefore :=> (Flip $ p1 `o` p0))
342260 , fromBefore :=> Fixup_Update (That $ To_Move $ toAfter :=> (p1 `o` p0))
343261 ]
@@ -347,7 +265,7 @@ instance ( GCompare k
347265 [fromBefore :=> Fixup_Update (That To_NonMove)]
348266 (To_Move (toAfter :=> p), From_Insert val) ->
349267 [toAfter :=> Fixup_Update (This $ From_Insert $ applyAlwaysHet2 p val)]
350− (To_Move (toAfter :=> p), From_Delete) ->
268+ (To_Move (toAfter :=> _), From_Delete) ->
351269 [toAfter :=> Fixup_Update (This From_Delete)]
352270 (To_NonMove, _) ->
353271 []
@@ -414,25 +332,31 @@ PatchDMapWithMove dstAfter srcAfter `mappendPatchDMapWithMoveSlow` PatchDMapWith
414332 src = DMap.mapMaybeWithKey g $ DMap.union srcAfter srcBefore
415333-}
416334
417−-- |Make a @'PatchDMapWithMove' k v@ which has the effect of inserting or updating a value @PatchTarget1 p a@ to the given key @k a@, like 'DMap.insert'.
335+-- | Make a @'PatchDMapWithMove' k v@ which has the effect of inserting or
336+-- updating a value @PatchTarget1 p a@ to the given key @k a@, like
337+-- 'DMap.insert'.
418338insertDMapKey :: k a -> PatchTarget1 p a -> PatchDMapWithMove k p
419339insertDMapKey k v =
420340 PatchDMapWithMove . DMap.singleton k $ NodeInfo (From_Insert v) To_NonMove
421341
422−-- |Make a @'PatchDMapWithMove' k v@ which has the effect of moving the value from the first key @k a@ to the second key @k a@, equivalent to:
342+-- | Make a @'PatchDMapWithMove' k v@ which has the effect of moving the value
343+-- from the first key @k a@ to the second key @k a@, equivalent to:
423344--
424345-- @
425346-- 'DMap.delete' src (maybe dmap ('DMap.insert' dst) (DMap.lookup src dmap))
426347-- @
427−moveDMapKey :: GCompare k => k a -> k a -> PatchDMapWithMove k (Proxy2 v)
348+moveDMapKey
349+ :: GCompare k
350+ => k a -> k a -> PatchDMapWithMove k (Proxy3 v)
428351moveDMapKey src dst = case src `geq` dst of
429352 Nothing -> PatchDMapWithMove $ DMap.fromList
430− [ dst :=> NodeInfo (From_Move (src :=> Cat.id)) To_NonMove
431− , src :=> NodeInfo From_Delete (To_Move $ dst :=> Proxy2)
353+ [ dst :=> NodeInfo (From_Move (src :=> Flip Proxy3)) To_NonMove
354+ , src :=> NodeInfo From_Delete (To_Move $ dst :=> Proxy3)
432355 ]
433− Just _ -> mempty
356+ Just _ -> PatchDMapWithMove DMap.empty
434357
435−-- |Make a @'PatchDMapWithMove' k v@ which has the effect of swapping two keys in the mapping, equivalent to:
358+-- | Make a @'PatchDMapWithMove' k v@ which has the effect of swapping two keys
359+-- in the mapping, equivalent to:
436360--
437361-- @
438362-- let aMay = DMap.lookup a dmap
@@ -441,17 +365,18 @@ moveDMapKey src dst = case src `geq` dst of
441365-- . maybe id (DMap.insert b) (aMay `mplus` bMay)
442366-- . DMap.delete a . DMap.delete b $ dmap
443367-- @
444−swapDMapKey :: GCompare k => k a -> k a -> PatchDMapWithMove k v
368+swapDMapKey :: GCompare k => k a -> k a -> PatchDMapWithMove k (Proxy3 v)
445369swapDMapKey src dst = case src `geq` dst of
446370 Nothing -> PatchDMapWithMove $ DMap.fromList
447− [ dst :=> NodeInfo (From_Move (src :=> Cat.id)) (ComposeMaybe $ Just src)
448− , src :=> NodeInfo (From_Move (dst :=> Cat.id)) (To_Move $ dst :=> Proxy2)
371+ [ dst :=> NodeInfo (From_Move (src :=> Flip Proxy3)) (To_Move $ src :=> Proxy3)
372+ , src :=> NodeInfo (From_Move (dst :=> Flip Proxy3)) (To_Move $ dst :=> Proxy3)
449373 ]
450− Just _ -> mempty
374+ Just _ -> PatchDMapWithMove DMap.empty
451375
452−-- |Make a @'PatchDMapWithMove' k v@ which has the effect of deleting a key in the mapping, equivalent to 'DMap.delete'.
376+-- | Make a @'PatchDMapWithMove' k v@ which has the effect of deleting a key in
377+-- the mapping, equivalent to 'DMap.delete'.
453378deleteDMapKey :: k a -> PatchDMapWithMove k v
454−deleteDMapKey k = PatchDMapWithMove $ DMap.singleton k $ NodeInfo From_Delete $ ComposeMaybe Nothing
379+deleteDMapKey k = PatchDMapWithMove $ DMap.singleton k $ NodeInfo From_Delete To_NonMove
455380
456381{-
457382k1, k2 :: Const2 Int () ()
@@ -477,17 +402,20 @@ dst (PatchDMapWithMove x _) = x
477402src (PatchDMapWithMove _ x) = x
478403-}
479404
480−-- |Extract the 'DMap' representing the patch changes from the 'PatchDMapWithMove'.
405+-- | Extract the 'DMap' representing the patch changes from the
406+-- 'PatchDMapWithMove'.
481407unPatchDMapWithMove :: PatchDMapWithMove k v -> DMap k (NodeInfo k v)
482408unPatchDMapWithMove (PatchDMapWithMove p) = p
483409
484−-- |Wrap a 'DMap' representing patch changes into a 'PatchDMapWithMove', without checking any invariants.
410+-- | Wrap a 'DMap' representing patch changes into a 'PatchDMapWithMove',
411+-- without checking any invariants.
485412--
486413-- __Warning:__ when using this function, you must ensure that the invariants of 'PatchDMapWithMove' are preserved; they will not be checked.
487414unsafePatchDMapWithMove :: DMap k (NodeInfo k v) -> PatchDMapWithMove k v
488415unsafePatchDMapWithMove = PatchDMapWithMove
489416
490−-- |Wrap a 'DMap' representing patch changes into a 'PatchDMapWithMove' while checking invariants. If the invariants are satisfied, @Right p@ is returned
417+-- | Wrap a 'DMap' representing patch changes into a 'PatchDMapWithMove' while
418+-- checking invariants. If the invariants are satisfied, @Right p@ is returned
491419-- otherwise @Left errors@.
492420patchDMapWithMove :: (GCompare k, GShow k) => DMap k (NodeInfo k v) -> Either [String] (PatchDMapWithMove k v)
493421patchDMapWithMove dm =
@@ -495,20 +423,28 @@ patchDMapWithMove dm =
495423 [] -> Right $ unsafePatchDMapWithMove dm
496424 errs -> Left errs
497425
498−-- |Map a natural transform @v -> v'@ over the given patch, transforming @'PatchDMapWithMove' k v@ into @'PatchDMapWithMove' k v'@.
426+-- | Map a natural transform @v -> v'@ over the given patch, transforming
427+-- @'PatchDMapWithMove' k v@ into @'PatchDMapWithMove' k v'@.
499428mapPatchDMapWithMove
500429 :: forall k p p'
501430 . (forall a. PatchTarget1 p a -> PatchTarget1 p' a)
502431 -> (forall from to. p from to -> p' from to)
503432 -> PatchDMapWithMove k p
504433 -> PatchDMapWithMove k p'
505−mapPatchDMapWithMove f g (PatchDMapWithMove p) = PatchDMapWithMove $
506− DMap.map (\ni -> ni { _nodeInfo_from = g $ _nodeInfo_from ni }) p
507− where g :: forall a. From k PatchTarget1 p a -> From k PatchTarget1 p' a
508− g = \case
434+mapPatchDMapWithMove f g (PatchDMapWithMove m) =
435+ PatchDMapWithMove $ DMap.map (\ni -> NodeInfo
436+ { _nodeInfo_from = h $ _nodeInfo_from ni
437+ , _nodeInfo_to = j $ _nodeInfo_to ni
438+ }) m
439+ where h :: forall a. From k p a -> From k p' a
440+ h = \case
509441 From_Insert v -> From_Insert $ f v
510442 From_Delete -> From_Delete
511− From_Move k p -> From_Move k $ g p
443+ From_Move (k :=> (Flip p)) -> From_Move $ k :=> Flip (g p)
444+ j :: forall a. To k p a -> To k p' a
445+ j = \case
446+ To_NonMove -> To_NonMove
447+ To_Move (k :=> p) -> To_Move $ k :=> g p
512448
513449-- | Traverse an effectful function @forall a. PatchTarget1 p a -> m (v ' a)@
514450-- over the given patch, transforming @'PatchDMapWithMove' k v@ into @m
@@ -517,9 +453,12 @@ traversePatchDMapWithMove
517453 :: forall m k p p'
518454 . Applicative m
519455 => (forall a. PatchTarget1 p a -> m (PatchTarget1 p' a))
456+ -> (forall from to. p from to -> m (p' from to))
520457 -> PatchDMapWithMove k p
521458 -> m (PatchDMapWithMove k p')
522−traversePatchDMapWithMove f = traversePatchDMapWithMoveWithKey $ const f
459+traversePatchDMapWithMove f g = traversePatchDMapWithMoveWithKey
460+ (\_ -> f)
461+ (\_ _ -> g)
523462
524463-- | Map an effectful function @forall a. k a -> PatchTarget1 p a -> m (v ' a)@
525464-- over the given patch, transforming @'PatchDMapWithMove' k v@ into @m
@@ -528,49 +467,67 @@ traversePatchDMapWithMoveWithKey
528467 :: forall m k p p'
529468 . Applicative m
530469 => (forall a. k a -> PatchTarget1 p a -> m (PatchTarget1 p' a))
470+ -> (forall from to. k from -> k to -> p from to -> m (p' from to))
531471 -> PatchDMapWithMove k p
532472 -> m (PatchDMapWithMove k p')
533−traversePatchDMapWithMoveWithKey f (PatchDMapWithMove p) =
534− PatchDMapWithMove <$> DMap.traverseWithKey (nodeInfoMapFromM . g) p
535− where g :: forall a. k a -> From k PatchTarget1 p a -> m (From k PatchTarget1 p' a)
536− g k = \case
473+traversePatchDMapWithMoveWithKey f g (PatchDMapWithMove m) =
474+ fmap PatchDMapWithMove $ DMap.traverseWithKey (\k ni -> NodeInfo
475+ <$> (h k $ _nodeInfo_from ni)
476+ <*> (j k $ _nodeInfo_to ni)) m
477+ where h :: forall a. k a -> From k p a -> m (From k p' a)
478+ h k = \case
537479 From_Insert v -> From_Insert <$> f k v
538480 From_Delete -> pure From_Delete
539− From_Move fromKey -> pure $ From_Move fromKey
481+ From_Move (fromKey :=> Flip p) -> From_Move . (fromKey :=>) . Flip <$> g fromKey k p
482+ j :: forall a. k a -> To k p a -> m (To k p' a)
483+ j k = \case
484+ To_NonMove -> pure To_NonMove
485+ To_Move (toKey :=> p) -> To_Move . (toKey :=>) <$> g k toKey p
540486
541487-- | Map a function which transforms @'From k PatchTarget1 p a@ into a @'From k
542488-- PatchTarget1 p' a@ over a @'NodeInfo' k PatchTarget1 p a@.
543489nodeInfoMapFrom
544490 :: (From k p a -> From k p' a)
491+ -> (To k p a -> To k p' a)
545492 -> NodeInfo k p a
546493 -> NodeInfo k p' a
547−nodeInfoMapFrom f ni = ni { _nodeInfo_from = f $ _nodeInfo_from ni }
494+nodeInfoMapFrom f g ni = NodeInfo
495+ { _nodeInfo_from = f $ _nodeInfo_from ni
496+ , _nodeInfo_to = g $ _nodeInfo_to ni
497+ }
548498
549499-- | Map an effectful function which transforms @'From k PatchTarget1 p a@ into
550500-- a @f ('From k PatchTarget1 p' a)@ over a @'NodeInfo' k PatchTarget1 p a@.
551501nodeInfoMapFromM
552− :: Functor f
502+ :: Applicative f
553503 => (From k p a -> f (From k p' a))
504+ -> (To k p a -> f (To k p' a))
554505 -> NodeInfo k p a
555506 -> f (NodeInfo k p' a)
556−nodeInfoMapFromM f ni = fmap (\result -> ni { _nodeInfo_from = result }) $ f $ _nodeInfo_from ni
507+nodeInfoMapFromM f g ni = NodeInfo
508+ <$> (f $ _nodeInfo_from ni)
509+ <*> (g $ _nodeInfo_to ni)
557510
558511-- | Weaken a 'PatchDMapWithMove' to a 'PatchMapWithMove' by weakening the keys
559512-- from @k a@ to @'Some' k@ and applying a given weakening function
560513-- @PatchTarget1 p a -> v'@ to values.
561514weakenPatchDMapWithMoveWith
562− :: forall k p v'
563− . (forall a. PatchTarget1 p a -> v')
515+ :: forall k p p'
516+ . (forall a. PatchTarget1 p a -> PatchTarget p')
517+ -> (forall from to. p from to -> p')
564518 -> PatchDMapWithMove k p
565− -> PatchMapWithMove (Some k) (Proxy v')
566−weakenPatchDMapWithMoveWith f (PatchDMapWithMove p) = PatchMapWithMove $ weakenDMapWith g p
567− where g :: forall a. NodeInfo k PatchTarget1 p a -> MapWithMove.NodeInfo (Some k) (Proxy v')
568− g ni = MapWithMove.NodeInfo
519+ -> PatchMapWithMove (Some k) p'
520+weakenPatchDMapWithMoveWith f g (PatchDMapWithMove m) =
521+ PatchMapWithMove $ weakenDMapWith h m
522+ where h :: forall a. NodeInfo k p a -> MapWithMove.NodeInfo (Some k) p'
523+ h ni = MapWithMove.NodeInfo
569524 { MapWithMove._nodeInfo_from = case _nodeInfo_from ni of
570525 From_Insert v -> MapWithMove.From_Insert $ f v
571526 From_Delete -> MapWithMove.From_Delete
572− From_Move k -> MapWithMove.From_Move (Some k) Proxy
573− , MapWithMove._nodeInfo_to = Some <$> getComposeMaybe (_nodeInfo_to ni)
527+ From_Move (k :=> Flip p) -> MapWithMove.From_Move (Some k) $ g p
528+ , MapWithMove._nodeInfo_to = case _nodeInfo_to ni of
529+ To_NonMove -> MapWithMove.To_NonMove
530+ To_Move (k :=> p) -> MapWithMove.To_Move (Some k) $ g p
574531 }
575532
576533-- | "Weaken" a @'PatchDMapWithMove' (Const2 k a) v@ to a @'PatchMapWithMove' k
@@ -578,17 +535,22 @@ weakenPatchDMapWithMoveWith f (PatchDMapWithMove p) = PatchMapWithMove $ weakenD
578535-- dependency in the typing and all points are already @a@, hence the function
579536-- to map each value to @v'@ is not higher rank.
580537patchDMapWithMoveToPatchMapWithMoveWith
581− :: forall k p v' a. (PatchTarget1 p a -> v')
538+ :: forall k p p' a
539+ . (PatchTarget1 p a -> PatchTarget p')
540+ -> (p a a -> p')
582541 -> PatchDMapWithMove (Const2 k a) p
583− -> PatchMapWithMove k (Proxy v')
584−patchDMapWithMoveToPatchMapWithMoveWith f (PatchDMapWithMove p) = PatchMapWithMove $ dmapToMapWith g p
585− where g :: NodeInfo (Const2 k a) PatchTarget1 p a -> MapWithMove.NodeInfo k (Proxy v')
586− g ni = MapWithMove.NodeInfo
542+ -> PatchMapWithMove k p'
543+patchDMapWithMoveToPatchMapWithMoveWith f g (PatchDMapWithMove m) =
544+ PatchMapWithMove $ dmapToMapWith h m
545+ where h :: NodeInfo (Const2 k a) p a -> MapWithMove.NodeInfo k p'
546+ h ni = MapWithMove.NodeInfo
587547 { MapWithMove._nodeInfo_from = case _nodeInfo_from ni of
588548 From_Insert v -> MapWithMove.From_Insert $ f v
589549 From_Delete -> MapWithMove.From_Delete
590− From_Move (Const2 k) -> MapWithMove.From_Move k Proxy
591− , MapWithMove._nodeInfo_to = unConst2 <$> getComposeMaybe (_nodeInfo_to ni)
550+ From_Move (Const2 k :=> Flip p) -> MapWithMove.From_Move k $ g p
551+ , MapWithMove._nodeInfo_to = case _nodeInfo_to ni of
552+ To_NonMove -> MapWithMove.To_NonMove
553+ To_Move (Const2 k :=> p) -> MapWithMove.To_Move k $ g p
592554 }
593555
594556-- | "Strengthen" a @'PatchMapWithMove' k v@ into a @'PatchDMapWithMove
@@ -597,36 +559,47 @@ patchDMapWithMoveToPatchMapWithMoveWith f (PatchDMapWithMove p) = PatchMapWithMo
597559-- 'Const2'. Apply the given function to each @v@ to produce a @PatchTarget1 p'
598560-- a@. Completemented by 'patchDMapWithMoveToPatchMapWithMoveWith'
599561const2PatchDMapWithMoveWith
600− :: forall k v p' a
601− . (v -> PatchTarget1 p' a)
562+ :: forall k v v' a
563+ . (v -> v' a)
602564 -> PatchMapWithMove k (Proxy v)
603− -> PatchDMapWithMove (Const2 k a) p'
604−const2PatchDMapWithMoveWith f (PatchMapWithMove p) = PatchDMapWithMove $ DMap.fromDistinctAscList $ g <$> Map.toAscList p
605− where g :: (k, MapWithMove.NodeInfo k (Proxy v)) -> DSum (Const2 k a) (NodeInfo (Const2 k a) v')
565+ -> PatchDMapWithMove (Const2 k a) (Proxy3 v')
566+const2PatchDMapWithMoveWith f (PatchMapWithMove p) =
567+ PatchDMapWithMove $ DMap.fromDistinctAscList $ g <$> Map.toAscList p
568+ where g :: (k, MapWithMove.NodeInfo k (Proxy v))
569+ -> DSum (Const2 k a) (NodeInfo (Const2 k a) (Proxy3 v'))
606570 g (k, ni) = Const2 k :=> NodeInfo
607571 { _nodeInfo_from = case MapWithMove._nodeInfo_from ni of
608572 MapWithMove.From_Insert v -> From_Insert $ f v
609573 MapWithMove.From_Delete -> From_Delete
610− MapWithMove.From_Move fromKey Proxy -> From_Move $ Const2 fromKey
611− , _nodeInfo_to = ComposeMaybe $ Const2 <$> MapWithMove._nodeInfo_to ni
574+ MapWithMove.From_Move fromKey Proxy -> From_Move $ Const2 fromKey :=> Flip Proxy3
575+ , _nodeInfo_to = case MapWithMove._nodeInfo_to ni of
576+ MapWithMove.To_NonMove -> To_NonMove
577+ MapWithMove.To_Move toKey Proxy -> To_Move $ Const2 toKey :=> Proxy3
612578 }
613579
614580-- | Apply the insertions, deletions, and moves to a given 'DMap'.
615−instance GCompare k => PatchHet (PatchDMapWithMove k p) where
581+instance ( GCompare k
582+ , PatchHet2 p
583+ , PatchSource1 p ~ PatchTarget1 p
584+ ) => PatchHet (PatchDMapWithMove k p) where
616585 type PatchSource (PatchDMapWithMove k p) = DMap k (PatchSource1 p)
617586 type PatchTarget (PatchDMapWithMove k p) = DMap k (PatchTarget1 p)
618−instance GCompare k => Patch (PatchDMapWithMove k p) where
619− apply (PatchDMapWithMove p) old = Just $! insertions `DMap.union` (old `DMap.difference` deletions)
587+
588+instance ( GCompare k
589+ , PatchHet2 p
590+ , PatchSource1 p ~ PatchTarget1 p
591+ ) => Patch (PatchDMapWithMove k p) where
592+ apply (PatchDMapWithMove m) old = Just $! insertions `DMap.union` (old `DMap.difference` deletions)
620593 -- TODO: return Nothing sometimes --Note: the strict application here is
621594 -- critical to ensuring that incremental merges don't hold onto all their
622595 -- prerequisite events forever; can we make this more robust?
623− where insertions = DMap.mapMaybeWithKey insertFunc p
596+ where insertions = DMap.mapMaybeWithKey insertFunc m
624597 insertFunc :: forall a. k a -> NodeInfo k p a -> Maybe (PatchTarget1 p a)
625598 insertFunc _ ni = case _nodeInfo_from ni of
626599 From_Insert v -> Just v
627− From_Move k -> DMap.lookup k old
600+ From_Move (k :=> Flip p) -> applyAlwaysHet2 p <$> DMap.lookup k old
628601 From_Delete -> Nothing
629− deletions = DMap.mapMaybeWithKey deleteFunc p
602+ deletions = DMap.mapMaybeWithKey deleteFunc m
630603 deleteFunc :: forall a. k a -> NodeInfo k p a -> Maybe (Constant () a)
631604 deleteFunc _ ni = case _nodeInfo_from ni of
632605 From_Delete -> Just $ Constant ()
@@ -634,6 +607,12 @@ instance GCompare k => Patch (PatchDMapWithMove k p) where
634607
635608-- | Get the values that will be replaced, deleted, or moved if the given patch
636609-- is applied to the given 'DMap'.
637−getDeletionsAndMoves :: GCompare k => PatchDMapWithMove k v -> DMap k v' -> DMap k (Product v' (ComposeMaybe k))
610+getDeletionsAndMoves
611+ :: ( GCompare k
612+ , PatchSource1 p ~ PatchTarget1 p
613+ )
614+ => PatchDMapWithMove k p
615+ -> DMap k (PatchSource1 p)
616+ -> DMap k (Product (PatchTarget1 p) (To k p))
638617getDeletionsAndMoves (PatchDMapWithMove p) m = DMap.intersectionWithKey f m p
639618 where f _ v ni = Pair v $ _nodeInfo_to ni
src/Data/Patch/MapWithMove.hs+62−41
@@ -41,7 +41,7 @@ deriving instance (Ord k, Ord p, Ord (PatchTarget p)) => Ord (PatchMapWithMove k
4141data NodeInfo k p = NodeInfo
4242 { _nodeInfo_from :: !(From k p)
4343 -- ^ Where do we get the new value for this key?
44− , _nodeInfo_to :: !(To k)
44+ , _nodeInfo_to :: !(To k p)
4545 -- ^ If the old value is being kept (i.e. moved rather than deleted or
4646 -- replaced), where is it going?
4747 }
@@ -64,14 +64,23 @@ deriving instance (Ord k, Ord p, Ord (PatchTarget p)) => Ord (From k p)
6464-- | Describe where a key's old value will go. If this is 'Just', that means
6565-- the key's old value will be moved to the given other key; if it is 'Nothing',
6666-- that means it will be deleted.
67−type To = Maybe
67+data To k p
68+ = To_NonMove
69+ | To_Move !k !p
70+
71+deriving instance (Show k, Show p, Show (PatchTarget p)) => Show (To k p)
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)
6875
6976-- | Create a 'PatchMapWithMove', validating it
7077patchMapWithMove
7178 :: Ord k => Map k (NodeInfo k p) -> Maybe (PatchMapWithMove k p)
7279patchMapWithMove m = if valid then Just $ PatchMapWithMove m else Nothing
7380 where valid = forwardLinks == backwardLinks
74− forwardLinks = Map.mapMaybe _nodeInfo_to m
81+ forwardLinks = flip Map.mapMaybe m $ \x -> case _nodeInfo_to x of
82+ To_NonMove -> Nothing
83+ To_Move to _ -> Just to
7584 backwardLinks = Map.fromList $ catMaybes $ flip fmap (Map.toList m) $ \(to, p) ->
7685 case _nodeInfo_from p of
7786 From_Move from _ -> Just (from, to)
@@ -82,7 +91,7 @@ patchMapWithMoveInsertAll
8291 :: Map k (PatchTarget p) -> PatchMapWithMove k p
8392patchMapWithMoveInsertAll m = PatchMapWithMove $ flip fmap m $ \v -> NodeInfo
8493 { _nodeInfo_from = From_Insert v
85− , _nodeInfo_to = Nothing
94+ , _nodeInfo_to = To_NonMove
8695 }
8796
8897-- | Extract the internal representation of the 'PatchMapWithMove'
@@ -93,7 +102,7 @@ unPatchMapWithMove (PatchMapWithMove p) = p
93102-- | Make a @'PatchMapWithMove' k p@ which has the effect of inserting or updating a value @v@ to the given key @k@, like 'Map.insert'.
94103insertMapKey
95104 :: k -> PatchTarget p -> PatchMapWithMove k p
96−insertMapKey k v = PatchMapWithMove . Map.singleton k $ NodeInfo (From_Insert v) Nothing
105+insertMapKey k v = PatchMapWithMove . Map.singleton k $ NodeInfo (From_Insert v) To_NonMove
97106
98107-- |Make a @'PatchMapWithMove' k p@ which has the effect of moving the value from the first key @k@ to the second key @k@, equivalent to:
99108--
@@ -106,8 +115,8 @@ moveMapKey src dst
106115 | src == dst = mempty
107116 | otherwise =
108117 PatchMapWithMove $ Map.fromList
109− [ (dst, NodeInfo (From_Move src mempty) Nothing)
110− , (src, NodeInfo From_Delete (Just dst))
118+ [ (dst, NodeInfo (From_Move src mempty) To_NonMove)
119+ , (src, NodeInfo From_Delete (To_Move dst mempty))
111120 ]
112121
113122-- |Make a @'PatchMapWithMove' k p@ which has the effect of swapping two keys in the mapping, equivalent to:
@@ -120,19 +129,21 @@ moveMapKey src dst
120129-- . Map.delete a . Map.delete b $ map
121130-- @
122131swapMapKey
123− :: (DecidablyEmpty p, Patch p) => Ord k => k -> k -> PatchMapWithMove k p
132+ :: (DecidablyEmpty p, Patch p)
133+ => Ord k => k -> k -> PatchMapWithMove k p
124134swapMapKey src dst
125135 | src == dst = mempty
126136 | otherwise =
127137 PatchMapWithMove $ Map.fromList
128− [ (dst, NodeInfo (From_Move src mempty) (Just src))
129− , (src, NodeInfo (From_Move dst mempty) (Just dst))
138+ [ (dst, NodeInfo (From_Move src mempty) (To_Move dst mempty))
139+ , (src, NodeInfo (From_Move dst mempty) (To_Move dst mempty))
130140 ]
131141
132−-- |Make a @'PatchMapWithMove' k v@ which has the effect of deleting a key in the mapping, equivalent to 'Map.delete'.
142+-- | Make a @'PatchMapWithMove' k v@ which has the effect of deleting a key in
143+-- the mapping, equivalent to 'Map.delete'.
133144deleteMapKey
134145 :: k -> PatchMapWithMove k v
135−deleteMapKey k = PatchMapWithMove . Map.singleton k $ NodeInfo From_Delete Nothing
146+deleteMapKey k = PatchMapWithMove . Map.singleton k $ NodeInfo From_Delete To_NonMove
136147
137148-- | Wrap a @'Map' k (NodeInfo k v)@ representing patch changes into a @'PatchMapWithMove' k v@, without checking any invariants.
138149--
@@ -145,6 +156,7 @@ unsafePatchMapWithMove = PatchMapWithMove
145156instance (Ord k, Patch p) => PatchHet (PatchMapWithMove k p) where
146157 type PatchSource (PatchMapWithMove k p) = Map k (PatchSource p)
147158 type PatchTarget (PatchMapWithMove k p) = Map k (PatchTarget p)
159+
148160instance (Ord k, Patch p) => Patch (PatchMapWithMove k p) where
149161 -- TODO: return Nothing sometimes
150162 -- Note: the strict application here is critical to ensuring that incremental
@@ -188,7 +200,7 @@ patchThatSortsMapWith cmp m = PatchMapWithMove $ Map.fromList $ catMaybes $ zipW
188200 reverseMapping = Map.fromList $ catMaybes $ zipWith f unsorted sorted
189201 g (to, _) (from, _) = if to == from then Nothing else
190202 let Just movingTo = Map.lookup from reverseMapping
191− in Just (to, NodeInfo (From_Move from mempty) $ Just movingTo)
203+ in Just (to, NodeInfo (From_Move from mempty) $ To_Move movingTo mempty)
192204
193205-- | Create a 'PatchMapWithMove' that, if applied to the first 'Map' provided,
194206-- will produce a 'Map' with the same values as the second 'Map' but with the
@@ -215,25 +227,32 @@ patchThatChangesMap oldByIndex newByIndex = patch
215227 then Map.delete v remainingValues
216228 else Map.insert v remainingKeys remainingValues
217229 case Map.lookup v remainingValues of
218− Nothing -> return $ NodeInfo (From_Insert v) $ Just undefined -- There's no existing value we can take
230+ Nothing -> return $ NodeInfo (From_Insert v) $ To_Move undefined undefined -- There's no existing value we can take
219231 Just fromKs ->
220232 if k `Set.member` fromKs
221233 then do
222234 putRemainingKeys $ Set.delete k fromKs
223− return $ NodeInfo (From_Move k mempty) $ Just undefined -- There's an existing value, and it's here, so no patch necessary
235+ return $ NodeInfo (From_Move k mempty) $ To_Move undefined undefined -- There's an existing value, and it's here, so no patch necessary
224236 else do
225237 (fromK, remainingKeys) <- return . fromJust $ Set.minView fromKs -- There's an existing value, but it's not here; move it here
226238 putRemainingKeys remainingKeys
227− return $ NodeInfo (From_Move fromK mempty) $ Just undefined
239+ return $ NodeInfo (From_Move fromK mempty) $ To_Move undefined undefined
228240 Map.traverseWithKey f newByIndex
229241 unusedOldKeys = fold unusedValuesByValue
230242 pointlessMove k = \case
231243 From_Move k' _ | k == k' -> True
232244 _ -> False
233245 keyWasMoved k = if k `Map.member` oldByIndex && not (k `Set.member` unusedOldKeys)
234− then Just undefined
235− else Nothing
236− patch = unsafePatchMapWithMove $ Map.filterWithKey (\k -> not . pointlessMove k . _nodeInfo_from) $ Map.mergeWithKey (\k a _ -> Just $ nodeInfoSetTo (keyWasMoved k) a) (Map.mapWithKey $ \k -> nodeInfoSetTo $ keyWasMoved k) (Map.mapWithKey $ \k _ -> NodeInfo From_Delete $ keyWasMoved k) insertsAndMoves oldByIndex
246+ then To_Move undefined undefined
247+ else To_NonMove
248+ patch = unsafePatchMapWithMove $ Map.filterWithKey
249+ (\k -> not . pointlessMove k . _nodeInfo_from)
250+ $ Map.mergeWithKey
251+ (\k a _ -> Just $ nodeInfoSetTo (keyWasMoved k) a)
252+ (Map.mapWithKey $ \k -> nodeInfoSetTo $ keyWasMoved k)
253+ (Map.mapWithKey $ \k _ -> NodeInfo From_Delete $ keyWasMoved k)
254+ insertsAndMoves
255+ oldByIndex
237256
238257-- | Change the 'From' value of a 'NodeInfo'
239258nodeInfoMapFrom
@@ -248,15 +267,16 @@ nodeInfoMapMFrom f ni = fmap (\result -> ni { _nodeInfo_from = result }) $ f $ _
248267
249268-- | Set the 'To' field of a 'NodeInfo'
250269nodeInfoSetTo
251− :: To k -> NodeInfo k v -> NodeInfo k v
270+ :: To k p -> NodeInfo k p -> NodeInfo k p
252271nodeInfoSetTo to ni = ni { _nodeInfo_to = to }
253272
254−-- |Helper data structure used for composing patches using the monoid instance.
255−data Fixup k v
273+-- | Helper data structure used for composing patches using the monoid instance.
274+data Fixup k p
256275 = Fixup_Delete
257− | Fixup_Update (These (From k v) (To k))
276+ | Fixup_Update (These (From k p) (To k p))
258277
259−-- |Compose patches having the same effect as applying the patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
278+-- | Compose patches having the same effect as applying the patches in turn:
279+-- @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
260280instance ( Ord k
261281 , DecidablyEmpty p
262282 , Patch p
@@ -264,18 +284,24 @@ instance ( Ord k
264284 PatchMapWithMove ma <> PatchMapWithMove mb = PatchMapWithMove m
265285 where
266286 connections = Map.toList $ Map.intersectionWithKey (\_ a b -> (_nodeInfo_to a, _nodeInfo_from b)) ma mb
267− h :: (k, (Maybe k, From k p)) -> [(k, Fixup k p)]
268− h (_, (mToAfter, editBefore)) = case (mToAfter, editBefore) of
269− (Just toAfter, From_Move fromBefore p)
270− | fromBefore == toAfter && isNull p
287+ h :: (k, (To k p, From k p)) -> [(k, Fixup k p)]
288+ h (_, (editAfter, editBefore)) = case (editAfter, editBefore) of
289+ (To_Move toAfter p1, From_Move fromBefore p0)
290+ | fromBefore == toAfter && isNull p0
271291 -> [(toAfter, Fixup_Delete)]
272292 | otherwise
273− -> [ (toAfter, Fixup_Update (This editBefore))
274− , (fromBefore, Fixup_Update (That mToAfter))
293+ -> [ (toAfter, Fixup_Update (This $ From_Move fromBefore $ p1 <> p0))
294+ , (fromBefore, Fixup_Update (That $ To_Move toAfter $ p1 <> p0))
275295 ]
276− (Nothing, From_Move fromBefore _) -> [(fromBefore, Fixup_Update (That mToAfter))] -- The item is destroyed in the second patch, so indicate that it is destroyed in the source map
277− (Just toAfter, _) -> [(toAfter, Fixup_Update (This editBefore))]
278− (Nothing, _) -> []
296+ (To_NonMove, From_Move fromBefore _) ->
297+ -- The item is destroyed in the second patch, so indicate that it is
298+ -- destroyed in the source map
299+ [(fromBefore, Fixup_Update (That editAfter))]
300+ (To_Move toAfter p, From_Insert val) ->
301+ [(toAfter, Fixup_Update $ This $ From_Insert $ applyAlways p val)]
302+ (To_Move toAfter _, From_Delete) ->
303+ [(toAfter, Fixup_Update $ This From_Delete)]
304+ (To_NonMove, _) -> []
279305 mergeFixups _ Fixup_Delete Fixup_Delete = Fixup_Delete
280306 mergeFixups _ (Fixup_Update a) (Fixup_Update b)
281307 | This x <- a, That y <- b
@@ -291,13 +317,7 @@ instance ( Ord k
291317 applyFixup _ ni = \case
292318 Fixup_Delete -> Nothing
293319 Fixup_Update u -> Just $ NodeInfo
294− { _nodeInfo_from = case _nodeInfo_from ni of
295− f@(From_Move _ p') -> case getHere u of -- The `from` fixup comes from the "old" patch
296− Nothing -> f -- If there's no `from` fixup, just use the "new" `from`
297− Just (From_Insert v) -> From_Insert $ applyAlways p' v
298− Just From_Delete -> From_Delete
299− Just (From_Move oldKey p) -> From_Move oldKey $ p' <> p
300− _ -> error "PatchMapWithMove: fixup for non-move From"
320+ { _nodeInfo_from = fromMaybe (_nodeInfo_from ni) $ getHere u
301321 , _nodeInfo_to = fromMaybe (_nodeInfo_to ni) $ getThere u
302322 }
303323 m = Map.differenceWithKey applyFixup (Map.unionWithKey combineNodeInfos ma mb) fixups
@@ -313,7 +333,8 @@ instance ( Ord k
313333 That b -> Just b
314334
315335--TODO: Figure out how to implement this in terms of PatchDMapWithMove rather than duplicating it here
316−-- |Compose patches having the same effect as applying the patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
336+-- | Compose patches having the same effect as applying the patches in turn:
337+-- @'applyAlways' (p <> q) == 'applyAlways' p . 'applyAlways' q@
317338instance ( Ord k
318339 , Monoid p
319340 , DecidablyEmpty p