@@ -8,6 +8,7 @@
88{-# LANGUAGE PatternGuards #-}
99{-# LANGUAGE PatternSynonyms #-}
1010{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE StandaloneDeriving #-}
1112{-# LANGUAGE TemplateHaskell #-}
1213{-# LANGUAGE TypeApplications #-}
1314{-# LANGUAGE TypeFamilies #-}
@@ -16,30 +17,59 @@
1617-- | 'Patch'es on 'Map' that can insert, delete, and move values from one key to
1718-- another
1819module Data.Patch.MapWithMove
19− ( module Data.Patch.MapWithMove
20− , PatchMapWithMove
20+ ( PatchMapWithMove
2121 ( PatchMapWithMove
2222 , -- | Extract the representation of the 'PatchMapWithMove' as a map of
2323 -- 'NodeInfo'.
2424 unPatchMapWithMove
2525 , ..
2626 )
27+ , patchMapWithMove
28+ , patchMapWithMoveInsertAll
29+ , insertMapKey
30+ , moveMapKey
31+ , swapMapKey
32+ , deleteMapKey
33+ , unsafePatchMapWithMove
34+ , patchMapWithMoveNewElements
35+ , patchMapWithMoveNewElementsMap
36+ , patchThatSortsMapWith
37+ , patchThatChangesAndSortsMapWith
38+ , patchThatChangesMap
39+
40+ -- * Node Info
2741 , NodeInfo
2842 ( NodeInfo
2943 , _nodeInfo_to
3044 , _nodeInfo_from
3145 , ..
3246 )
33− -- TODO export these under the type consructor once GHC is fixed
34− -- , From (From_Insert, From_Delete, From_Move)
47+ , bitraverseNodeInfo
48+ , nodeInfoMapFrom
49+ , nodeInfoMapMFrom
50+ , nodeInfoSetTo
51+
52+ -- * From
53+ , From
54+ ( From_Insert
55+ , From_Delete
56+ , From_Move
57+ , ..
58+ )
59+ , bitraverseFrom
60+
61+ -- * To
62+ , To
3563 ) where
3664
3765import Data.Coerce
66+import Data.Kind (Type)
3867import Data.Patch.Class
3968import Data.Patch.MapWithPatchingMove
4069 ( PatchMapWithPatchingMove (..)
4170 )
4271import qualified Data.Patch.MapWithPatchingMove as PM
72+import Data.Patch.MapWithPatchingMove (To) -- already a transparent synonym
4373
4474import Control.Lens hiding (from, to)
4575import Data.List
@@ -54,7 +84,7 @@ import Data.Traversable (foldMapDefault)
5484-- | Patch a Map with additions, deletions, and moves. Invariant: If key @k1@
5585-- is coming from @From_Move k2@, then key @k2@ should be going to @Just k1@,
5686-- 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'
5888 { -- | Extract the underlying 'PatchMapWithPatchingMove k (Proxy v)'
5989 unPatchMapWithMove' :: PatchMapWithPatchingMove k (Proxy v)
6090 }
@@ -66,10 +96,14 @@ newtype PatchMapWithMove k v = PatchMapWithMove'
6696 , Monoid
6797 )
6898
99+pattern Coerce :: Coercible a b => a -> b
100+pattern Coerce x <- (coerce -> x)
101+ where Coerce x = coerce x
102+
69103{-# COMPLETE PatchMapWithMove #-}
70104pattern PatchMapWithMove :: Map k (NodeInfo k v) -> PatchMapWithMove k v
71−pattern PatchMapWithMove { unPatchMapWithMove } <- PatchMapWithMove' (PatchMapWithPatchingMove (coerce -> unPatchMapWithMove))
72− where PatchMapWithMove m = PatchMapWithMove' $ PatchMapWithPatchingMove $ coerce m
105+unPatchMapWithMove :: PatchMapWithMove k v -> Map k (NodeInfo k v)
106+pattern PatchMapWithMove { unPatchMapWithMove } = PatchMapWithMove' (PatchMapWithPatchingMove (Coerce unPatchMapWithMove))
73107
74108_PatchMapWithMove
75109 :: Iso
@@ -100,55 +134,6 @@ instance TraversableWithIndex k (PatchMapWithMove k) where
100134 itraversed <.
101135 traverse
102136
103−newtype NodeInfo k v = NodeInfo' { unNodeInfo' :: PM.NodeInfo k (Proxy v) }
104− deriving ( Show, Read, Eq, Ord
105− )
106−
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
113− })
114−
115−_NodeInfo
116− :: Iso
117− (NodeInfo k0 v0)
118− (NodeInfo k1 v1)
119− (PM.NodeInfo k0 (Proxy v0))
120− (PM.NodeInfo k1 (Proxy v1))
121−_NodeInfo = iso unNodeInfo' NodeInfo'
122−
123−instance Functor (NodeInfo k) where
124− fmap f = runIdentity . traverse (Identity . f)
125−
126−instance Foldable (NodeInfo k) where
127− foldMap = foldMapDefault
128−
129−instance Traversable (NodeInfo k) where
130− traverse = _NodeInfo . traverseNodeInfo
131− where
132− traverseNodeInfo
133− :: Traversal (PM.NodeInfo k (Proxy a)) (PM.NodeInfo k (Proxy b)) a b
134− traverseNodeInfo = PM.bitraverseNodeInfo pure (\ ~Proxy -> pure Proxy)
135−
136−type From k v = PM.From k (Proxy v)
137−
138−{-# COMPLETE From_Insert, From_Delete, From_Move #-}
139−
140−pattern From_Insert :: v -> From k v
141−pattern From_Insert v = PM.From_Insert v
142−
143−pattern From_Delete :: From k v
144−pattern From_Delete = PM.From_Delete
145−
146−pattern From_Move :: k -> From k v
147−pattern From_Move k = PM.From_Move k Proxy
148−
149−type To k = PM.To k
150−
151−
152137-- | Create a 'PatchMapWithMove', validating it
153138patchMapWithMove :: Ord k => Map k (NodeInfo k v) -> Maybe (PatchMapWithMove k v)
154139patchMapWithMove = fmap coerce . PM.patchMapWithPatchingMove . coerce
@@ -224,9 +209,62 @@ patchThatChangesMap :: (Ord k, Ord v) => Map k v -> Map k v -> PatchMapWithMove
224209patchThatChangesMap oldByIndex newByIndex = PatchMapWithMove' $
225210 PM.patchThatChangesMap oldByIndex newByIndex
226211
212+--
213+-- NodeInfo
214+--
215+
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) }
219+
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)
224+
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
233+ })
234+
235+_NodeInfo
236+ :: Iso
237+ (NodeInfo k0 v0)
238+ (NodeInfo k1 v1)
239+ (PM.NodeInfo k0 (Proxy v0))
240+ (PM.NodeInfo k1 (Proxy v1))
241+_NodeInfo = iso unNodeInfo' NodeInfo'
242+
243+instance Functor (NodeInfo k) where
244+ fmap f = runIdentity . traverse (Identity . f)
245+
246+instance Foldable (NodeInfo k) where
247+ foldMap = foldMapDefault
248+
249+instance Traversable (NodeInfo k) where
250+ traverse = _NodeInfo . traverseNodeInfo
251+ where
252+ traverseNodeInfo
253+ :: Traversal (PM.NodeInfo k (Proxy a)) (PM.NodeInfo k (Proxy b)) a b
254+ traverseNodeInfo = PM.bitraverseNodeInfo pure (\ ~Proxy -> pure Proxy)
255+
256+bitraverseNodeInfo
257+ :: Applicative f
258+ => (k0 -> f k1)
259+ -> (v0 -> f v1)
260+ -> NodeInfo k0 v0 -> f (NodeInfo k1 v1)
261+bitraverseNodeInfo fk fv = fmap coerce
262+ . PM.bitraverseNodeInfo fk (\ ~Proxy -> pure Proxy) fv
263+ . coerce
264+
227265-- | Change the 'From' value of a 'NodeInfo'
228266nodeInfoMapFrom :: (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
230268
231269-- | Change the 'From' value of a 'NodeInfo', using a 'Functor' (or
232270-- 'Applicative', 'Monad', etc.) action to get the new value
@@ -234,11 +272,43 @@ nodeInfoMapMFrom
234272 :: Functor f
235273 => (From k v -> f (From k v))
236274 -> 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')
277+ . coerce
238278
239279-- | Set the 'To' field of a 'NodeInfo'
240280nodeInfoSetTo :: To k -> NodeInfo k v -> NodeInfo k v
241281nodeInfoSetTo = coerce . PM.nodeInfoSetTo
242282
283+--
284+-- From
285+--
286+
287+-- | Describe how a key's new value should be produced
288+newtype From k (v :: Type) = From' { unFrom' :: PM.From k (Proxy v) }
289+
290+{-# COMPLETE From_Insert, From_Delete, From_Move #-}
291+
292+-- | Insert the given value here
293+pattern From_Insert :: v -> From k v
294+pattern From_Insert v = From' (PM.From_Insert v)
295+
296+-- | Delete the existing value, if any, from here
297+pattern From_Delete :: From k v
298+pattern From_Delete = From' (PM.From_Delete)
299+
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)
303+
304+bitraverseFrom
305+ :: Applicative f
306+ => (k0 -> f k1)
307+ -> (v0 -> f v1)
308+ -> From k0 v0 -> f (From k1 v1)
309+bitraverseFrom fk fv = fmap coerce
310+ . PM.bitraverseFrom fk (\ ~Proxy -> pure Proxy) fv
311+ . coerce
312+
243313makeWrapped ''PatchMapWithMove
244314makeWrapped ''NodeInfo