@@ -8,7 +8,6 @@
8{-# LANGUAGE PatternGuards #-}
8{-# LANGUAGE PatternGuards #-}
9{-# LANGUAGE PatternSynonyms #-}
9{-# LANGUAGE PatternSynonyms #-}
10{-# LANGUAGE ScopedTypeVariables #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11−{-# LANGUAGE StandaloneDeriving #-}
12{-# LANGUAGE TemplateHaskell #-}
11{-# LANGUAGE TemplateHaskell #-}
13{-# LANGUAGE TypeApplications #-}
12{-# LANGUAGE TypeApplications #-}
14{-# LANGUAGE TypeFamilies #-}
13{-# LANGUAGE TypeFamilies #-}
@@ -17,56 +16,32 @@
17-- | 'Patch'es on 'Map' that can insert, delete, and move values from one key to
16-- | 'Patch'es on 'Map' that can insert, delete, and move values from one key to
19module Data.Patch.MapWithMove
18module 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− , unPatchMapWithMove
24+ unPatchMapWithMove
26− , patchMapWithMoveInsertAll
31− , unsafePatchMapWithMove
32− , patchMapWithMoveNewElements
33− , patchMapWithMoveNewElementsMap
34− , patchThatSortsMapWith
35− , patchThatChangesAndSortsMapWith
36− , patchThatChangesMap
39 , NodeInfo
27 , NodeInfo
40 ( NodeInfo
28 ( NodeInfo
41 , _nodeInfo_to
29 , _nodeInfo_to
42 , _nodeInfo_from
30 , _nodeInfo_from
45− , bitraverseNodeInfo
33+ -- TODO export these under the type consructor once GHC is fixed
52− ( From_Insert
34+ -- , From (From_Insert, From_Delete, From_Move)
63import Data.Coerce
37import Data.Coerce
64−import Data.Kind (Type)
65import Data.Patch.Class
38import Data.Patch.Class
66−import Data.Patch.MapWithPatchingMove (PatchMapWithPatchingMove(..), To)
39+import Data.Patch.MapWithPatchingMove
40+ ( PatchMapWithPatchingMove (..)
67−import qualified Data.Patch.MapWithPatchingMove as PM -- already a transparent synonym
42+import qualified Data.Patch.MapWithPatchingMove as PM
69−import Control.Lens
44+import Control.Lens hiding (from, to)
70import Data.List
45import Data.List
71import Data.Map (Map)
46import Data.Map (Map)
72import qualified Data.Map as Map
47import qualified Data.Map as Map
@@ -79,32 +54,22 @@ import Data.Traversable (foldMapDefault)
79-- | Patch a Map with additions, deletions, and moves. Invariant: If key @k1@
54-- | Patch a Map with additions, deletions, and moves. Invariant: If key @k1@
80-- is coming from @From_Move k2@, then key @k2@ should be going to @Just k1@,
55-- is coming from @From_Move k2@, then key @k2@ should be going to @Just k1@,
81-- and vice versa. There should never be any unpaired From/To keys.
56-- and vice versa. There should never be any unpaired From/To keys.
82−newtype PatchMapWithMove k (v :: Type) = PatchMapWithMove'
57+newtype PatchMapWithMove k v = PatchMapWithMove'
83 { -- | Extract the underlying 'PatchMapWithPatchingMove k (Proxy v)'
58 { -- | Extract the underlying 'PatchMapWithPatchingMove k (Proxy v)'
84 unPatchMapWithMove' :: PatchMapWithPatchingMove k (Proxy v)
59 unPatchMapWithMove' :: PatchMapWithPatchingMove k (Proxy v)
86 deriving ( Show, Read, Eq, Ord
61 deriving ( Show, Read, Eq, Ord
87−-- Haddock cannot handle documentation here before GHC 8.6
89−#if __GLASGOW_HASKELL__ >= 806
90− -- | Compose patches having the same effect as applying the
62+ , -- | Compose patches having the same effect as applying the
91 -- patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p .
63 -- patches in turn: @'applyAlways' (p <> q) == 'applyAlways' p .
92 -- 'applyAlways' q@
64 -- 'applyAlways' q@
98−pattern Coerce :: Coercible a b => a -> b
99−pattern Coerce x <- (coerce -> x)
100− where Coerce x = coerce x
102{-# COMPLETE PatchMapWithMove #-}
69{-# COMPLETE PatchMapWithMove #-}
103pattern PatchMapWithMove :: Map k (NodeInfo k v) -> PatchMapWithMove k v
70pattern PatchMapWithMove :: Map k (NodeInfo k v) -> PatchMapWithMove k v
104−-- | Extract the representation of the 'PatchMapWithMove' as a map of
71+pattern PatchMapWithMove { unPatchMapWithMove } <- PatchMapWithMove' (PatchMapWithPatchingMove (coerce -> unPatchMapWithMove))
106−unPatchMapWithMove :: PatchMapWithMove k v -> Map k (NodeInfo k v)
107−pattern PatchMapWithMove { unPatchMapWithMove } = PatchMapWithMove' (PatchMapWithPatchingMove (Coerce unPatchMapWithMove))
72+ where PatchMapWithMove m = PatchMapWithMove' $ PatchMapWithPatchingMove $ coerce m
109_PatchMapWithMove
74_PatchMapWithMove
@@ -135,9 +100,58 @@ instance TraversableWithIndex k (PatchMapWithMove k) where
135 itraversed <.
100 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
138-- | Create a 'PatchMapWithMove', validating it
152-- | Create a 'PatchMapWithMove', validating it
139patchMapWithMove :: Ord k => Map k (NodeInfo k v) -> Maybe (PatchMapWithMove k v)
153patchMapWithMove :: Ord k => Map k (NodeInfo k v) -> Maybe (PatchMapWithMove k v)
140−patchMapWithMove = fmap PatchMapWithMove' . PM.patchMapWithPatchingMove . coerce
154+patchMapWithMove = fmap coerce . PM.patchMapWithPatchingMove . coerce
142-- | Create a 'PatchMapWithMove' that inserts everything in the given 'Map'
156-- | Create a 'PatchMapWithMove' that inserts everything in the given 'Map'
143patchMapWithMoveInsertAll :: Map k v -> PatchMapWithMove k v
157patchMapWithMoveInsertAll :: Map k v -> PatchMapWithMove k v
@@ -160,8 +174,8 @@ moveMapKey src dst = PatchMapWithMove' $ PM.moveMapKey src dst
161-- let aMay = Map.lookup a map
175-- let aMay = Map.lookup a map
162-- bMay = Map.lookup b map
176-- bMay = Map.lookup b map
163−-- in maybe id (Map.insert a) (bMay <> aMay)
177+-- in maybe id (Map.insert a) (bMay `mplus` aMay)
164−-- . maybe id (Map.insert b) (aMay <> bMay)
178+-- . maybe id (Map.insert b) (aMay `mplus` bMay)
165-- . Map.delete a . Map.delete b $ map
179-- . Map.delete a . Map.delete b $ map
167swapMapKey :: Ord k => k -> k -> PatchMapWithMove k v
181swapMapKey :: Ord k => k -> k -> PatchMapWithMove k v
@@ -175,7 +189,7 @@ deleteMapKey = PatchMapWithMove' . PM.deleteMapKey
176-- __Warning:__ when using this function, you must ensure that the invariants of 'PatchMapWithMove' are preserved; they will not be checked.
190-- __Warning:__ when using this function, you must ensure that the invariants of 'PatchMapWithMove' are preserved; they will not be checked.
177unsafePatchMapWithMove :: Map k (NodeInfo k v) -> PatchMapWithMove k v
191unsafePatchMapWithMove :: Map k (NodeInfo k v) -> PatchMapWithMove k v
178−unsafePatchMapWithMove = coerce PM.unsafePatchMapWithPatchingMove
192+unsafePatchMapWithMove = PatchMapWithMove' . PM.unsafePatchMapWithPatchingMove . coerce
180-- | Apply the insertions, deletions, and moves to a given 'Map'
194-- | Apply the insertions, deletions, and moves to a given 'Map'
181instance Ord k => Patch (PatchMapWithMove k v) where
195instance Ord k => Patch (PatchMapWithMove k v) where
@@ -199,7 +213,7 @@ patchThatSortsMapWith cmp = PatchMapWithMove' . PM.patchThatSortsMapWith cmp
199-- | Create a 'PatchMapWithMove' that, if applied to the first 'Map' provided,
213-- | Create a 'PatchMapWithMove' that, if applied to the first 'Map' provided,
200-- will produce a 'Map' with the same values as the second 'Map' but with the
214-- will produce a 'Map' with the same values as the second 'Map' but with the
201-- values sorted with the given ordering function.
215-- values sorted with the given ordering function.
202−patchThatChangesAndSortsMapWith :: (Ord k, Ord v) => (v -> v -> Ordering) -> Map k v -> Map k v -> PatchMapWithMove k v
216+patchThatChangesAndSortsMapWith :: forall k v. (Ord k, Ord v) => (v -> v -> Ordering) -> Map k v -> Map k v -> PatchMapWithMove k v
203patchThatChangesAndSortsMapWith cmp oldByIndex newByIndexUnsorted = patchThatChangesMap oldByIndex newByIndex
217patchThatChangesAndSortsMapWith cmp oldByIndex newByIndexUnsorted = patchThatChangesMap oldByIndex newByIndex
204 where newList = Map.toList newByIndexUnsorted
218 where newList = Map.toList newByIndexUnsorted
205 newByIndex = Map.fromList $ zip (fst <$> newList) $ sortBy cmp $ snd <$> newList
219 newByIndex = Map.fromList $ zip (fst <$> newList) $ sortBy cmp $ snd <$> newList
@@ -210,58 +224,9 @@ patchThatChangesMap :: (Ord k, Ord v) => Map k v -> Map k v -> PatchMapWithMove
210patchThatChangesMap oldByIndex newByIndex = PatchMapWithMove' $
224patchThatChangesMap oldByIndex newByIndex = PatchMapWithMove' $
211 PM.patchThatChangesMap oldByIndex newByIndex
225 PM.patchThatChangesMap oldByIndex newByIndex
217−-- | Holds the information about each key: where its new value should come from,
218−-- and where its old value should go to
219−newtype NodeInfo k (v :: Type) = NodeInfo' { unNodeInfo' :: PM.NodeInfo k (Proxy v) }
221−deriving instance (Show k, Show p) => Show (NodeInfo k p)
222−deriving instance (Read k, Read p) => Read (NodeInfo k p)
223−deriving instance (Eq k, Eq p) => Eq (NodeInfo k p)
224−deriving instance (Ord k, Ord p) => Ord (NodeInfo k p)
226−{-# COMPLETE NodeInfo #-}
227−pattern NodeInfo :: To k -> From k v -> NodeInfo k v
228−_nodeInfo_to :: NodeInfo k v -> To k
229−_nodeInfo_from :: NodeInfo k v -> From k v
230−pattern NodeInfo { _nodeInfo_to, _nodeInfo_from } = NodeInfo'
232− { PM._nodeInfo_to = _nodeInfo_to
233− , PM._nodeInfo_from = Coerce _nodeInfo_from
240− (PM.NodeInfo k0 (Proxy v0))
241− (PM.NodeInfo k1 (Proxy v1))
242−_NodeInfo = iso unNodeInfo' NodeInfo'
244−instance Functor (NodeInfo k) where
245− fmap f = runIdentity . traverse (Identity . f)
247−instance Foldable (NodeInfo k) where
248− foldMap = foldMapDefault
250−instance Traversable (NodeInfo k) where
251− traverse = bitraverseNodeInfo pure
257− -> NodeInfo k0 v0 -> f (NodeInfo k1 v1)
258−bitraverseNodeInfo fk fv = fmap NodeInfo'
259− . PM.bitraverseNodeInfo fk (\ ~Proxy -> pure Proxy) fv
262-- | Change the 'From' value of a 'NodeInfo'
227-- | Change the 'From' value of a 'NodeInfo'
263nodeInfoMapFrom :: (From k v -> From k v) -> NodeInfo k v -> NodeInfo k v
228nodeInfoMapFrom :: (From k v -> From k v) -> NodeInfo k v -> NodeInfo k v
264−nodeInfoMapFrom f = coerce $ PM.nodeInfoMapFrom (unFrom' . f . From')
229+nodeInfoMapFrom = coerce . PM.nodeInfoMapFrom
266-- | Change the 'From' value of a 'NodeInfo', using a 'Functor' (or
231-- | Change the 'From' value of a 'NodeInfo', using a 'Functor' (or
267-- 'Applicative', 'Monad', etc.) action to get the new value
232-- 'Applicative', 'Monad', etc.) action to get the new value
@@ -269,44 +234,11 @@ nodeInfoMapMFrom
269 :: Functor f
234 :: Functor f
270 => (From k v -> f (From k v))
235 => (From k v -> f (From k v))
271 -> NodeInfo k v -> f (NodeInfo k v)
236 -> NodeInfo k v -> f (NodeInfo k v)
272−nodeInfoMapMFrom f = fmap NodeInfo'
237+nodeInfoMapMFrom f = fmap coerce . PM.nodeInfoMapMFrom f . coerce
273− . PM.nodeInfoMapMFrom (fmap unFrom' . f . From')
276-- | Set the 'To' field of a 'NodeInfo'
239-- | Set the 'To' field of a 'NodeInfo'
277nodeInfoSetTo :: To k -> NodeInfo k v -> NodeInfo k v
240nodeInfoSetTo :: To k -> NodeInfo k v -> NodeInfo k v
278nodeInfoSetTo = coerce . PM.nodeInfoSetTo
241nodeInfoSetTo = coerce . PM.nodeInfoSetTo
284−-- | Describe how a key's new value should be produced
285−newtype From k (v :: Type) = From' { unFrom' :: PM.From k (Proxy v) }
287−{-# COMPLETE From_Insert, From_Delete, From_Move #-}
289−-- | Insert the given value here
290−pattern From_Insert :: v -> From k v
291−pattern From_Insert v = From' (PM.From_Insert v)
293−-- | Delete the existing value, if any, from here
294−pattern From_Delete :: From k v
295−pattern From_Delete = From' PM.From_Delete
297−-- | Move the value here from the given key
298−pattern From_Move :: k -> From k v
299−pattern From_Move k = From' (PM.From_Move k Proxy)
305− -> From k0 v0 -> f (From k1 v1)
306−bitraverseFrom fk fv = fmap From'
307− . PM.bitraverseFrom fk (\ ~Proxy -> pure Proxy) fv
310makeWrapped ''PatchMapWithMove
243makeWrapped ''PatchMapWithMove
311makeWrapped ''NodeInfo
244makeWrapped ''NodeInfo