{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
module Data.Patch.MapWithMove
( PatchMapWithMove
( PatchMapWithMove
, unPatchMapWithMove
, ..
)
, patchMapWithMove
, patchMapWithMoveInsertAll
, insertMapKey
, moveMapKey
, swapMapKey
, deleteMapKey
, unsafePatchMapWithMove
, patchMapWithMoveNewElements
, patchMapWithMoveNewElementsMap
, patchThatSortsMapWith
, patchThatChangesAndSortsMapWith
, patchThatChangesMap
, NodeInfo
( NodeInfo
, _nodeInfo_from
, _nodeInfo_to
, ..
)
, bitraverseNodeInfo
, nodeInfoMapFrom
, nodeInfoMapMFrom
, nodeInfoSetTo
, From
( From_Insert
, From_Delete
, From_Move
, ..
)
, bitraverseFrom
, To
) where
import Data.Coerce
import Data.Kind (Type)
import Data.Patch.Class
import Data.Patch.MapWithPatchingMove (PatchMapWithPatchingMove(..), To)
import qualified Data.Patch.MapWithPatchingMove as PM
import Control.Lens hiding (FunctorWithIndex, FoldableWithIndex, TraversableWithIndex)
#if !MIN_VERSION_lens(5,0,0)
import qualified Control.Lens as L
#endif
import Data.List
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Proxy
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup (Semigroup (..))
#endif
import Data.Traversable (foldMapDefault)
import Data.Functor.WithIndex
import Data.Foldable.WithIndex
import Data.Traversable.WithIndex
newtype PatchMapWithMove k (v :: Type) = PatchMapWithMove'
{
unPatchMapWithMove' :: PatchMapWithPatchingMove k (Proxy v)
}
deriving ( Show, Read, Eq, Ord
,
#if __GLASGOW_HASKELL__ >= 806
#endif
Semigroup
, Monoid
)
pattern Coerce :: Coercible a b => a -> b
pattern Coerce x <- (coerce -> x)
where Coerce x = coerce x
{-# COMPLETE PatchMapWithMove #-}
pattern PatchMapWithMove :: Map k (NodeInfo k v) -> PatchMapWithMove k v
unPatchMapWithMove :: PatchMapWithMove k v -> Map k (NodeInfo k v)
pattern PatchMapWithMove { unPatchMapWithMove } = PatchMapWithMove' (PatchMapWithPatchingMove (Coerce unPatchMapWithMove))
_PatchMapWithMove
:: Iso
(PatchMapWithMove k0 v0)
(PatchMapWithMove k1 v1)
(Map k0 (NodeInfo k0 v0))
(Map k1 (NodeInfo k1 v1))
_PatchMapWithMove = iso unPatchMapWithMove PatchMapWithMove
instance Functor (PatchMapWithMove k) where
fmap f = runIdentity . traverse (Identity . f)
instance Foldable (PatchMapWithMove k) where
foldMap = foldMapDefault
instance Traversable (PatchMapWithMove k) where
traverse =
_PatchMapWithMove .
traverse .
traverse
instance FunctorWithIndex k (PatchMapWithMove k)
instance FoldableWithIndex k (PatchMapWithMove k)
instance TraversableWithIndex k (PatchMapWithMove k) where
itraverse = (_PatchMapWithMove .> itraversed <. traverse) . Indexed
#if !MIN_VERSION_lens(5,0,0)
instance L.FunctorWithIndex k (PatchMapWithMove k) where imap = Data.Functor.WithIndex.imap
instance L.FoldableWithIndex k (PatchMapWithMove k) where ifoldMap = Data.Foldable.WithIndex.ifoldMap
instance L.TraversableWithIndex k (PatchMapWithMove k) where itraverse = Data.Traversable.WithIndex.itraverse
#endif
patchMapWithMove :: Ord k => Map k (NodeInfo k v) -> Maybe (PatchMapWithMove k v)
patchMapWithMove = fmap PatchMapWithMove' . PM.patchMapWithPatchingMove . coerce
patchMapWithMoveInsertAll :: Map k v -> PatchMapWithMove k v
patchMapWithMoveInsertAll = PatchMapWithMove' . PM.patchMapWithPatchingMoveInsertAll
insertMapKey :: k -> v -> PatchMapWithMove k v
insertMapKey k v = PatchMapWithMove' $ PM.insertMapKey k v
moveMapKey :: Ord k => k -> k -> PatchMapWithMove k v
moveMapKey src dst = PatchMapWithMove' $ PM.moveMapKey src dst
swapMapKey :: Ord k => k -> k -> PatchMapWithMove k v
swapMapKey src dst = PatchMapWithMove' $ PM.swapMapKey src dst
deleteMapKey :: k -> PatchMapWithMove k v
deleteMapKey = PatchMapWithMove' . PM.deleteMapKey
unsafePatchMapWithMove :: Map k (NodeInfo k v) -> PatchMapWithMove k v
unsafePatchMapWithMove = coerce PM.unsafePatchMapWithPatchingMove
instance Ord k => Patch (PatchMapWithMove k v) where
type PatchTarget (PatchMapWithMove k v) = Map k v
apply (PatchMapWithMove' p) = apply p
patchMapWithMoveNewElements :: PatchMapWithMove k v -> [v]
patchMapWithMoveNewElements = PM.patchMapWithPatchingMoveNewElements . unPatchMapWithMove'
patchMapWithMoveNewElementsMap :: PatchMapWithMove k v -> Map k v
patchMapWithMoveNewElementsMap = PM.patchMapWithPatchingMoveNewElementsMap . unPatchMapWithMove'
patchThatSortsMapWith :: Ord k => (v -> v -> Ordering) -> Map k v -> PatchMapWithMove k v
patchThatSortsMapWith cmp = PatchMapWithMove' . PM.patchThatSortsMapWith cmp
patchThatChangesAndSortsMapWith :: (Ord k, Ord v) => (v -> v -> Ordering) -> Map k v -> Map k v -> PatchMapWithMove k v
patchThatChangesAndSortsMapWith cmp oldByIndex newByIndexUnsorted = patchThatChangesMap oldByIndex newByIndex
where newList = Map.toList newByIndexUnsorted
newByIndex = Map.fromList $ zip (fst <$> newList) $ sortBy cmp $ snd <$> newList
patchThatChangesMap :: (Ord k, Ord v) => Map k v -> Map k v -> PatchMapWithMove k v
patchThatChangesMap oldByIndex newByIndex = PatchMapWithMove' $
PM.patchThatChangesMap oldByIndex newByIndex
newtype NodeInfo k (v :: Type) = NodeInfo' { unNodeInfo' :: PM.NodeInfo k (Proxy v) }
deriving instance (Show k, Show p) => Show (NodeInfo k p)
deriving instance (Read k, Read p) => Read (NodeInfo k p)
deriving instance (Eq k, Eq p) => Eq (NodeInfo k p)
deriving instance (Ord k, Ord p) => Ord (NodeInfo k p)
{-# COMPLETE NodeInfo #-}
pattern NodeInfo :: From k v -> To k -> NodeInfo k v
_nodeInfo_from :: NodeInfo k v -> From k v
_nodeInfo_to :: NodeInfo k v -> To k
pattern NodeInfo { _nodeInfo_from, _nodeInfo_to } = NodeInfo'
PM.NodeInfo
{ PM._nodeInfo_from = Coerce _nodeInfo_from
, PM._nodeInfo_to = _nodeInfo_to
}
_NodeInfo
:: Iso
(NodeInfo k0 v0)
(NodeInfo k1 v1)
(PM.NodeInfo k0 (Proxy v0))
(PM.NodeInfo k1 (Proxy v1))
_NodeInfo = iso unNodeInfo' NodeInfo'
instance Functor (NodeInfo k) where
fmap f = runIdentity . traverse (Identity . f)
instance Foldable (NodeInfo k) where
foldMap = foldMapDefault
instance Traversable (NodeInfo k) where
traverse = bitraverseNodeInfo pure
bitraverseNodeInfo
:: Applicative f
=> (k0 -> f k1)
-> (v0 -> f v1)
-> NodeInfo k0 v0 -> f (NodeInfo k1 v1)
bitraverseNodeInfo fk fv = fmap NodeInfo'
. PM.bitraverseNodeInfo fk (\ ~Proxy -> pure Proxy) fv
. coerce
nodeInfoMapFrom :: (From k v -> From k v) -> NodeInfo k v -> NodeInfo k v
nodeInfoMapFrom f = coerce $ PM.nodeInfoMapFrom (unFrom' . f . From')
nodeInfoMapMFrom
:: Functor f
=> (From k v -> f (From k v))
-> NodeInfo k v -> f (NodeInfo k v)
nodeInfoMapMFrom f = fmap NodeInfo'
. PM.nodeInfoMapMFrom (fmap unFrom' . f . From')
. coerce
nodeInfoSetTo :: To k -> NodeInfo k v -> NodeInfo k v
nodeInfoSetTo = coerce . PM.nodeInfoSetTo
newtype From k (v :: Type) = From' { unFrom' :: PM.From k (Proxy v) }
{-# COMPLETE From_Insert, From_Delete, From_Move #-}
pattern From_Insert :: v -> From k v
pattern From_Insert v = From' (PM.From_Insert v)
pattern From_Delete :: From k v
pattern From_Delete = From' PM.From_Delete
pattern From_Move :: k -> From k v
pattern From_Move k = From' (PM.From_Move k Proxy)
bitraverseFrom
:: Applicative f
=> (k0 -> f k1)
-> (v0 -> f v1)
-> From k0 v0 -> f (From k1 v1)
bitraverseFrom fk fv = fmap From'
. PM.bitraverseFrom fk (\ ~Proxy -> pure Proxy) fv
. coerce
makeWrapped ''PatchMapWithMove
makeWrapped ''NodeInfo
makeWrapped ''From