@@ -8,6 +8,7 @@
8{-# LANGUAGE PatternGuards #-}
8{-# LANGUAGE PatternGuards #-}
9{-# LANGUAGE PatternSynonyms #-}
9{-# LANGUAGE PatternSynonyms #-}
10{-# LANGUAGE ScopedTypeVariables #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE StandaloneDeriving #-}
11{-# LANGUAGE TemplateHaskell #-}
12{-# LANGUAGE TemplateHaskell #-}
12{-# LANGUAGE TypeApplications #-}
13{-# LANGUAGE TypeApplications #-}
13{-# LANGUAGE TypeFamilies #-}
14{-# LANGUAGE TypeFamilies #-}
@@ -16,30 +17,59 @@
16-- | 'Patch'es on 'Map' that can insert, delete, and move values from one key to
17-- | 'Patch'es on 'Map' that can insert, delete, and move values from one key to
18module Data.Patch.MapWithMove
19module Data.Patch.MapWithMove
19− ( module Data.Patch.MapWithMove
20− , PatchMapWithMove
20+ ( PatchMapWithMove
21 ( PatchMapWithMove
21 ( PatchMapWithMove
22 , -- | Extract the representation of the 'PatchMapWithMove' as a map of
22 , -- | Extract the representation of the 'PatchMapWithMove' as a map of
23 -- 'NodeInfo'.
23 -- 'NodeInfo'.
24 unPatchMapWithMove
24 unPatchMapWithMove
28+ , patchMapWithMoveInsertAll
33+ , unsafePatchMapWithMove
34+ , patchMapWithMoveNewElements
35+ , patchMapWithMoveNewElementsMap
36+ , patchThatSortsMapWith
37+ , patchThatChangesAndSortsMapWith
38+ , patchThatChangesMap
27 , NodeInfo
41 , NodeInfo
28 ( NodeInfo
42 ( NodeInfo
29 , _nodeInfo_to
43 , _nodeInfo_to
30 , _nodeInfo_from
44 , _nodeInfo_from
33− -- TODO export these under the type consructor once GHC is fixed
47+ , bitraverseNodeInfo
34− -- , From (From_Insert, From_Delete, From_Move)
54+ ( From_Insert
37import Data.Coerce
65import Data.Coerce
66+import Data.Kind (Type)
38import Data.Patch.Class
67import Data.Patch.Class
39import Data.Patch.MapWithPatchingMove
68import Data.Patch.MapWithPatchingMove
40 ( PatchMapWithPatchingMove (..)
69 ( PatchMapWithPatchingMove (..)
42import qualified Data.Patch.MapWithPatchingMove as PM
71import qualified Data.Patch.MapWithPatchingMove as PM
72+import Data.Patch.MapWithPatchingMove (To) -- already a transparent synonym
44import Control.Lens hiding (from, to)
74import Control.Lens hiding (from, to)
45import Data.List
75import Data.List
@@ -54,7 +84,7 @@ import Data.Traversable (foldMapDefault)
54-- | Patch a Map with additions, deletions, and moves. Invariant: If key @k1@
84-- | Patch a Map with additions, deletions, and moves. Invariant: If key @k1@
55-- is coming from @From_Move k2@, then key @k2@ should be going to @Just k1@,
85-- is coming from @From_Move k2@, then key @k2@ should be going to @Just k1@,
56-- and vice versa. There should never be any unpaired From/To keys.
86-- and vice versa. There should never be any unpaired From/To keys.
57−newtype PatchMapWithMove k v = PatchMapWithMove'
87+newtype PatchMapWithMove k (v :: Type) = PatchMapWithMove'
58 { -- | Extract the underlying 'PatchMapWithPatchingMove k (Proxy v)'
88 { -- | Extract the underlying 'PatchMapWithPatchingMove k (Proxy v)'
59 unPatchMapWithMove' :: PatchMapWithPatchingMove k (Proxy v)
89 unPatchMapWithMove' :: PatchMapWithPatchingMove k (Proxy v)
@@ -66,10 +96,14 @@ newtype PatchMapWithMove k v = PatchMapWithMove'
99+pattern Coerce :: Coercible a b => a -> b
100+pattern Coerce x <- (coerce -> x)
101+ where Coerce x = coerce x
69{-# COMPLETE PatchMapWithMove #-}
103{-# COMPLETE PatchMapWithMove #-}
70pattern PatchMapWithMove :: Map k (NodeInfo k v) -> PatchMapWithMove k v
104pattern PatchMapWithMove :: Map k (NodeInfo k v) -> PatchMapWithMove k v
71−pattern PatchMapWithMove { unPatchMapWithMove } <- PatchMapWithMove' (PatchMapWithPatchingMove (coerce -> unPatchMapWithMove))
105+unPatchMapWithMove :: PatchMapWithMove k v -> Map k (NodeInfo k v)
72− where PatchMapWithMove m = PatchMapWithMove' $ PatchMapWithPatchingMove $ coerce m
106+pattern PatchMapWithMove { unPatchMapWithMove } = PatchMapWithMove' (PatchMapWithPatchingMove (Coerce unPatchMapWithMove))
74_PatchMapWithMove
108_PatchMapWithMove
@@ -100,55 +134,6 @@ instance TraversableWithIndex k (PatchMapWithMove k) where
100 itraversed <.
134 itraversed <.
103−newtype NodeInfo k v = NodeInfo' { unNodeInfo' :: PM.NodeInfo k (Proxy v) }
104− deriving ( Show, Read, Eq, Ord
107−{-# COMPLETE NodeInfo #-}
108−pattern NodeInfo :: To k -> From k v -> NodeInfo k v
109−pattern NodeInfo { _nodeInfo_to, _nodeInfo_from } =
110− NodeInfo' (PM.NodeInfo
111− { PM._nodeInfo_to = _nodeInfo_to
112− , PM._nodeInfo_from = _nodeInfo_from
119− (PM.NodeInfo k0 (Proxy v0))
120− (PM.NodeInfo k1 (Proxy v1))
121−_NodeInfo = iso unNodeInfo' NodeInfo'
123−instance Functor (NodeInfo k) where
124− fmap f = runIdentity . traverse (Identity . f)
126−instance Foldable (NodeInfo k) where
127− foldMap = foldMapDefault
129−instance Traversable (NodeInfo k) where
130− traverse = _NodeInfo . traverseNodeInfo
133− :: Traversal (PM.NodeInfo k (Proxy a)) (PM.NodeInfo k (Proxy b)) a b
134− traverseNodeInfo = PM.bitraverseNodeInfo pure (\ ~Proxy -> pure Proxy)
136−type From k v = PM.From k (Proxy v)
138−{-# COMPLETE From_Insert, From_Delete, From_Move #-}
140−pattern From_Insert :: v -> From k v
141−pattern From_Insert v = PM.From_Insert v
143−pattern From_Delete :: From k v
144−pattern From_Delete = PM.From_Delete
146−pattern From_Move :: k -> From k v
147−pattern From_Move k = PM.From_Move k Proxy
152-- | Create a 'PatchMapWithMove', validating it
137-- | Create a 'PatchMapWithMove', validating it
153patchMapWithMove :: Ord k => Map k (NodeInfo k v) -> Maybe (PatchMapWithMove k v)
138patchMapWithMove :: Ord k => Map k (NodeInfo k v) -> Maybe (PatchMapWithMove k v)
154patchMapWithMove = fmap coerce . PM.patchMapWithPatchingMove . coerce
139patchMapWithMove = fmap coerce . PM.patchMapWithPatchingMove . coerce
@@ -224,9 +209,62 @@ patchThatChangesMap :: (Ord k, Ord v) => Map k v -> Map k v -> PatchMapWithMove
224patchThatChangesMap oldByIndex newByIndex = PatchMapWithMove' $
209patchThatChangesMap oldByIndex newByIndex = PatchMapWithMove' $
225 PM.patchThatChangesMap oldByIndex newByIndex
210 PM.patchThatChangesMap oldByIndex newByIndex
216+-- | Holds the information about each key: where its new value should come from,
217+-- and where its old value should go to
218+newtype NodeInfo k (v :: Type) = NodeInfo' { unNodeInfo' :: PM.NodeInfo k (Proxy v) }
220+deriving instance (Show k, Show p) => Show (NodeInfo k p)
221+deriving instance (Read k, Read p) => Read (NodeInfo k p)
222+deriving instance (Eq k, Eq p) => Eq (NodeInfo k p)
223+deriving instance (Ord k, Ord p) => Ord (NodeInfo k p)
225+{-# COMPLETE NodeInfo #-}
226+pattern NodeInfo :: To k -> From k v -> NodeInfo k v
227+_nodeInfo_to :: NodeInfo k v -> To k
228+_nodeInfo_from :: NodeInfo k v -> From k v
229+pattern NodeInfo { _nodeInfo_to, _nodeInfo_from } =
230+ NodeInfo' (PM.NodeInfo
231+ { PM._nodeInfo_to = _nodeInfo_to
232+ , PM._nodeInfo_from = Coerce _nodeInfo_from
239+ (PM.NodeInfo k0 (Proxy v0))
240+ (PM.NodeInfo k1 (Proxy v1))
241+_NodeInfo = iso unNodeInfo' NodeInfo'
243+instance Functor (NodeInfo k) where
244+ fmap f = runIdentity . traverse (Identity . f)
246+instance Foldable (NodeInfo k) where
247+ foldMap = foldMapDefault
249+instance Traversable (NodeInfo k) where
250+ traverse = _NodeInfo . traverseNodeInfo
253+ :: Traversal (PM.NodeInfo k (Proxy a)) (PM.NodeInfo k (Proxy b)) a b
254+ traverseNodeInfo = PM.bitraverseNodeInfo pure (\ ~Proxy -> pure Proxy)
260+ -> NodeInfo k0 v0 -> f (NodeInfo k1 v1)
261+bitraverseNodeInfo fk fv = fmap coerce
262+ . PM.bitraverseNodeInfo fk (\ ~Proxy -> pure Proxy) fv
227-- | Change the 'From' value of a 'NodeInfo'
265-- | Change the 'From' value of a 'NodeInfo'
228nodeInfoMapFrom :: (From k v -> From k v) -> NodeInfo k v -> NodeInfo k v
266nodeInfoMapFrom :: (From k v -> From k v) -> NodeInfo k v -> NodeInfo k v
229−nodeInfoMapFrom = coerce . PM.nodeInfoMapFrom
267+nodeInfoMapFrom f = coerce . PM.nodeInfoMapFrom (unFrom' . f . From') . coerce
231-- | Change the 'From' value of a 'NodeInfo', using a 'Functor' (or
269-- | Change the 'From' value of a 'NodeInfo', using a 'Functor' (or
232-- 'Applicative', 'Monad', etc.) action to get the new value
270-- 'Applicative', 'Monad', etc.) action to get the new value
@@ -234,11 +272,43 @@ nodeInfoMapMFrom
234 :: Functor f
272 :: Functor f
235 => (From k v -> f (From k v))
273 => (From k v -> f (From k v))
236 -> NodeInfo k v -> f (NodeInfo k v)
274 -> NodeInfo k v -> f (NodeInfo k v)
237−nodeInfoMapMFrom f = fmap coerce . PM.nodeInfoMapMFrom f . coerce
275+nodeInfoMapMFrom f = fmap coerce
276+ . PM.nodeInfoMapMFrom (fmap unFrom' . f . From')
239-- | Set the 'To' field of a 'NodeInfo'
279-- | Set the 'To' field of a 'NodeInfo'
240nodeInfoSetTo :: To k -> NodeInfo k v -> NodeInfo k v
280nodeInfoSetTo :: To k -> NodeInfo k v -> NodeInfo k v
241nodeInfoSetTo = coerce . PM.nodeInfoSetTo
281nodeInfoSetTo = coerce . PM.nodeInfoSetTo
287+-- | Describe how a key's new value should be produced
288+newtype From k (v :: Type) = From' { unFrom' :: PM.From k (Proxy v) }
290+{-# COMPLETE From_Insert, From_Delete, From_Move #-}
292+-- | Insert the given value here
293+pattern From_Insert :: v -> From k v
294+pattern From_Insert v = From' (PM.From_Insert v)
296+-- | Delete the existing value, if any, from here
297+pattern From_Delete :: From k v
298+pattern From_Delete = From' (PM.From_Delete)
300+-- | Move the value here from the given key
301+pattern From_Move :: k -> From k v
302+pattern From_Move k = From' (PM.From_Move k Proxy)
308+ -> From k0 v0 -> f (From k1 v1)
309+bitraverseFrom fk fv = fmap coerce
310+ . PM.bitraverseFrom fk (\ ~Proxy -> pure Proxy) fv
243makeWrapped ''PatchMapWithMove
313makeWrapped ''PatchMapWithMove
244makeWrapped ''NodeInfo
314makeWrapped ''NodeInfo