{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Patch.IntMap where
import Control.Lens
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as IntMap
import Data.Maybe
import Data.Semigroup
import Data.Patch.Class
newtype PatchIntMap a = PatchIntMap { unPatchIntMap :: IntMap (Maybe a) }
deriving ( Show, Read, Eq, Ord
, Functor, Foldable, Traversable, Monoid
)
instance Semigroup (PatchIntMap v) where
PatchIntMap a <> PatchIntMap b = PatchIntMap $ a `mappend` b
stimes = stimesIdempotentMonoid
makeWrapped ''PatchIntMap
instance Patch (PatchIntMap a) where
type PatchTarget (PatchIntMap a) = IntMap a
apply (PatchIntMap p) v = if IntMap.null p then Nothing else Just $
let removes = IntMap.filter isNothing p
adds = IntMap.mapMaybe id p
in IntMap.union adds $ v `IntMap.difference` removes
instance FunctorWithIndex Int PatchIntMap
instance FoldableWithIndex Int PatchIntMap
instance TraversableWithIndex Int PatchIntMap where
itraverse = itraversed . Indexed
itraversed = _Wrapped .> itraversed <. traversed
mapIntMapPatchWithKey :: (Int -> a -> b) -> PatchIntMap a -> PatchIntMap b
mapIntMapPatchWithKey f (PatchIntMap m) = PatchIntMap $ IntMap.mapWithKey (\ k mv -> f k <$> mv) m
traverseIntMapPatchWithKey :: Applicative f => (Int -> a -> f b) -> PatchIntMap a -> f (PatchIntMap b)
traverseIntMapPatchWithKey f (PatchIntMap m) = PatchIntMap <$> IntMap.traverseWithKey (\k mv -> traverse (f k) mv) m
patchIntMapNewElements :: PatchIntMap a -> [a]
patchIntMapNewElements (PatchIntMap m) = catMaybes $ IntMap.elems m
patchIntMapNewElementsMap :: PatchIntMap a -> IntMap a
patchIntMapNewElementsMap (PatchIntMap m) = IntMap.mapMaybe id m
getDeletions :: PatchIntMap v -> IntMap v' -> IntMap v'
getDeletions (PatchIntMap m) v = IntMap.intersection v m