{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeFamilies #-}
module Reflex.Patch.Map where
import Reflex.Patch.Class
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe
import Data.Semigroup
newtype PatchMap k v = PatchMap { unPatchMap :: Map k (Maybe v) }
deriving (Show, Read, Eq, Ord)
instance Ord k => Patch (PatchMap k v) where
type PatchTarget (PatchMap k v) = Map k v
{-# INLINABLE apply #-}
apply (PatchMap p) old = Just $! insertions `Map.union` (old `Map.difference` deletions)
where insertions = Map.mapMaybeWithKey (const id) p
deletions = Map.mapMaybeWithKey (const nothingToJust) p
nothingToJust = \case
Nothing -> Just ()
Just _ -> Nothing
instance Ord k => Semigroup (PatchMap k v) where
PatchMap a <> PatchMap b = PatchMap $ a `mappend` b
#if MIN_VERSION_semigroups(0,17,0)
stimes = stimesIdempotentMonoid
#else
times1p n x = case compare n 0 of
LT -> error "stimesIdempotentMonoid: negative multiplier"
EQ -> mempty
GT -> x
#endif
instance Ord k => Monoid (PatchMap k v) where
mempty = PatchMap mempty
mappend = (<>)
instance Functor (PatchMap k) where
fmap f = PatchMap . fmap (fmap f) . unPatchMap
patchMapNewElements :: PatchMap k v -> [v]
patchMapNewElements (PatchMap p) = catMaybes $ Map.elems p
patchMapNewElementsMap :: PatchMap k v -> Map k v
patchMapNewElementsMap (PatchMap p) = Map.mapMaybe id p