-- inspired by total-map
module Data.Graph.Comfort.TotalMap where

import Control.Applicative (Applicative, pure, (<*>))

import qualified Data.Map as Map
import Data.Map (Map)
import Data.Monoid ((<>))


data TotalMap k a = TotalMap {forall k a. TotalMap k a -> a
deflt :: a, forall k a. TotalMap k a -> Map k a
core :: Map k a}

cons :: a -> Map k a -> TotalMap k a
cons :: forall a k. a -> Map k a -> TotalMap k a
cons = forall k a. a -> Map k a -> TotalMap k a
TotalMap


instance Functor (TotalMap k) where
   fmap :: forall a b. (a -> b) -> TotalMap k a -> TotalMap k b
fmap a -> b
f (TotalMap a
d Map k a
m) = forall k a. a -> Map k a -> TotalMap k a
TotalMap (a -> b
f a
d) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Map k a
m)

instance (Ord k) => Applicative (TotalMap k) where
   pure :: forall a. a -> TotalMap k a
pure a
a = forall k a. a -> Map k a -> TotalMap k a
TotalMap a
a forall k a. Map k a
Map.empty
   TotalMap a -> b
fd Map k (a -> b)
fm <*> :: forall a b. TotalMap k (a -> b) -> TotalMap k a -> TotalMap k b
<*> TotalMap a
ad Map k a
am =
      forall k a. a -> Map k a -> TotalMap k a
TotalMap (a -> b
fd a
ad) forall a b. (a -> b) -> a -> b
$
         forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> a -> b
$a
ad) (forall k a b. Ord k => Map k a -> Map k b -> Map k a
Map.difference Map k (a -> b)
fm Map k a
am) forall a. Semigroup a => a -> a -> a
<>
         forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> b
fdforall a b. (a -> b) -> a -> b
$) (forall k a b. Ord k => Map k a -> Map k b -> Map k a
Map.difference Map k a
am Map k (a -> b)
fm) forall a. Semigroup a => a -> a -> a
<>
         forall k a b c.
Ord k =>
(a -> b -> c) -> Map k a -> Map k b -> Map k c
Map.intersectionWith forall a b. (a -> b) -> a -> b
($) Map k (a -> b)
fm Map k a
am

intersectionPartialWith ::
   (Ord k) =>
   (a -> b -> c) -> TotalMap k a -> Map k b -> Map k c
intersectionPartialWith :: forall k a b c.
Ord k =>
(a -> b -> c) -> TotalMap k a -> Map k b -> Map k c
intersectionPartialWith a -> b -> c
f (TotalMap a
ad Map k a
am) Map k b
bm =
   forall k a b c.
Ord k =>
(a -> b -> c) -> Map k a -> Map k b -> Map k c
Map.intersectionWith a -> b -> c
f Map k a
am Map k b
bm
   forall k a. Ord k => Map k a -> Map k a -> Map k a
`Map.union`
   forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> b -> c
f a
ad) Map k b
bm