-- |
-- Module      : Streamly.Internal.Data.IsMap
-- Copyright   : (c) 2022 Composewell Technologies
-- License     : BSD-3-Clause
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC

module Streamly.Internal.Data.IsMap (IsMap(..)) where

import Data.Kind (Type)
import Data.Map.Strict (Map)

import qualified Data.IntMap.Strict as IntMap
import qualified Data.Map.Strict as Map

-- XXX Try unpacked-containers

class IsMap f where
    type Key f :: Type

    mapEmpty :: f a
    mapAlterF :: Functor g =>
        (Maybe a -> g (Maybe a)) -> Key f -> f a -> g (f a)
    -- These can be implemented in terms of alterF itself
    mapLookup :: Key f -> f a -> Maybe a
    mapInsert :: Key f -> a -> f a -> f a
    mapDelete :: Key f -> f a -> f a
    mapUnion :: f a -> f a -> f a
    mapNull :: f a -> Bool
    mapTraverseWithKey ::
        Applicative t => (Key f -> a -> t b) -> f a -> t (f b)

instance Ord k => IsMap (Map k) where
    type Key (Map k) = k

    mapEmpty :: forall a. Map k a
mapEmpty = Map k a
forall k a. Map k a
Map.empty
    mapAlterF :: forall (g :: * -> *) a.
Functor g =>
(Maybe a -> g (Maybe a)) -> Key (Map k) -> Map k a -> g (Map k a)
mapAlterF = (Maybe a -> g (Maybe a)) -> k -> Map k a -> g (Map k a)
(Maybe a -> g (Maybe a)) -> Key (Map k) -> Map k a -> g (Map k a)
forall (f :: * -> *) k a.
(Functor f, Ord k) =>
(Maybe a -> f (Maybe a)) -> k -> Map k a -> f (Map k a)
Map.alterF
    mapLookup :: forall a. Key (Map k) -> Map k a -> Maybe a
mapLookup = k -> Map k a -> Maybe a
Key (Map k) -> Map k a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup
    mapInsert :: forall a. Key (Map k) -> a -> Map k a -> Map k a
mapInsert = k -> a -> Map k a -> Map k a
Key (Map k) -> a -> Map k a -> Map k a
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert
    mapDelete :: forall a. Key (Map k) -> Map k a -> Map k a
mapDelete = k -> Map k a -> Map k a
Key (Map k) -> Map k a -> Map k a
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete
    mapUnion :: forall a. Map k a -> Map k a -> Map k a
mapUnion = Map k a -> Map k a -> Map k a
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union
    mapNull :: forall a. Map k a -> Bool
mapNull = Map k a -> Bool
forall k a. Map k a -> Bool
Map.null
    mapTraverseWithKey :: forall (t :: * -> *) a b.
Applicative t =>
(Key (Map k) -> a -> t b) -> Map k a -> t (Map k b)
mapTraverseWithKey = (k -> a -> t b) -> Map k a -> t (Map k b)
(Key (Map k) -> a -> t b) -> Map k a -> t (Map k b)
forall (t :: * -> *) k a b.
Applicative t =>
(k -> a -> t b) -> Map k a -> t (Map k b)
Map.traverseWithKey

instance IsMap IntMap.IntMap where
    type Key IntMap.IntMap = Int

    mapEmpty :: forall a. IntMap a
mapEmpty = IntMap a
forall a. IntMap a
IntMap.empty
    mapAlterF :: forall (g :: * -> *) a.
Functor g =>
(Maybe a -> g (Maybe a)) -> Key IntMap -> IntMap a -> g (IntMap a)
mapAlterF = (Maybe a -> g (Maybe a)) -> Key -> IntMap a -> g (IntMap a)
(Maybe a -> g (Maybe a)) -> Key IntMap -> IntMap a -> g (IntMap a)
forall (f :: * -> *) a.
Functor f =>
(Maybe a -> f (Maybe a)) -> Key -> IntMap a -> f (IntMap a)
IntMap.alterF
    mapLookup :: forall a. Key IntMap -> IntMap a -> Maybe a
mapLookup = Key -> IntMap a -> Maybe a
Key IntMap -> IntMap a -> Maybe a
forall a. Key -> IntMap a -> Maybe a
IntMap.lookup
    mapInsert :: forall a. Key IntMap -> a -> IntMap a -> IntMap a
mapInsert = Key -> a -> IntMap a -> IntMap a
Key IntMap -> a -> IntMap a -> IntMap a
forall a. Key -> a -> IntMap a -> IntMap a
IntMap.insert
    mapDelete :: forall a. Key IntMap -> IntMap a -> IntMap a
mapDelete = Key -> IntMap a -> IntMap a
Key IntMap -> IntMap a -> IntMap a
forall a. Key -> IntMap a -> IntMap a
IntMap.delete
    mapUnion :: forall a. IntMap a -> IntMap a -> IntMap a
mapUnion = IntMap a -> IntMap a -> IntMap a
forall a. IntMap a -> IntMap a -> IntMap a
IntMap.union
    mapNull :: forall a. IntMap a -> Bool
mapNull = IntMap a -> Bool
forall a. IntMap a -> Bool
IntMap.null
    mapTraverseWithKey :: forall (t :: * -> *) a b.
Applicative t =>
(Key IntMap -> a -> t b) -> IntMap a -> t (IntMap b)
mapTraverseWithKey = (Key -> a -> t b) -> IntMap a -> t (IntMap b)
(Key IntMap -> a -> t b) -> IntMap a -> t (IntMap b)
forall (t :: * -> *) a b.
Applicative t =>
(Key -> a -> t b) -> IntMap a -> t (IntMap b)
IntMap.traverseWithKey