{-# LANGUAGE ScopedTypeVariables #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Language.Haskell.TH.Desugar.OMap
-- Copyright   :  (C) 2016-2018 Daniel Wagner, 2019 Ryan Scott
-- License     :  BSD-style (see LICENSE)
-- Maintainer  :  Ryan Scott
-- Stability   :  experimental
-- Portability :  non-portable
--
-- An 'OMap' behaves much like a 'M.Map', with all the same asymptotics, but
-- also remembers the order that keys were inserted.
--
-- This module offers a simplified version of the "Data.Map.Ordered.Strict" API
-- that assumes left-biased indices everywhere and uses a different 'Semigroup'
-- instance (the one in this module uses @('<>') = 'union'@) and 'Monoid'
-- instance (the one in this module uses @'mappend' = 'union'@).
--
----------------------------------------------------------------------------
module Language.Haskell.TH.Desugar.OMap.Strict
    ( OMap(..)
    -- * Trivial maps
    , empty, singleton
    -- * Insertion
    , insertPre, insertPost, union, unionWithKey
    -- * Deletion
    , delete, filterWithKey, (\\), intersection, intersectionWithKey
    -- * Query
    , null, size, member, notMember, lookup
    -- * Indexing
    , Index, lookupIndex, lookupAt
    -- * List conversions
    , fromList, assocs, toAscList
    -- * 'M.Map' conversion
    , toMap
    ) where

import Data.Coerce
import qualified Data.Map.Strict as M (Map)
import Data.Map.Ordered.Strict (Index)
import qualified Data.Map.Ordered.Strict as OM
import Language.Haskell.TH.Desugar.OMap (OMap(..))
import Prelude hiding (filter, lookup, null)

empty :: forall k v. OMap k v
empty :: OMap k v
empty = OMap k v -> OMap k v
coerce (OMap k v
forall k v. OMap k v
OM.empty :: OM.OMap k v)

singleton :: k -> v -> OMap k v
singleton :: k -> v -> OMap k v
singleton k
k v
v = OMap k v -> OMap k v
coerce ((k, v) -> OMap k v
forall k v. (k, v) -> OMap k v
OM.singleton (k
k, v
v))

-- | The value's index will be lower than the indices of the values in the
-- 'OSet'.
insertPre :: Ord k => k -> v -> OMap k v -> OMap k v
insertPre :: k -> v -> OMap k v -> OMap k v
insertPre k
k v
v = (OMap k v -> OMap k v) -> OMap k v -> OMap k v
coerce ((k
k, v
v) (k, v) -> OMap k v -> OMap k v
forall k v. Ord k => (k, v) -> OMap k v -> OMap k v
OM.|<)

-- | The value's index will be higher than the indices of the values in the
-- 'OSet'.
insertPost :: Ord k => OMap k v -> k -> v -> OMap k v
insertPost :: OMap k v -> k -> v -> OMap k v
insertPost OMap k v
m k
k v
v = OMap k v -> OMap k v
coerce (OMap k v -> OMap k v
coerce OMap k v
m OMap k v -> (k, v) -> OMap k v
forall k v. Ord k => OMap k v -> (k, v) -> OMap k v
OM.|> (k
k, v
v))

union :: forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
union :: OMap k v -> OMap k v -> OMap k v
union = (OMap k v -> OMap k v -> OMap k v)
-> OMap k v -> OMap k v -> OMap k v
coerce (OMap k v -> OMap k v -> OMap k v
forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
(OM.|<>) :: OM.OMap k v -> OM.OMap k v -> OM.OMap k v)

unionWithKey :: Ord k => (k -> v -> v -> v) -> OMap k v -> OMap k v -> OMap k v
unionWithKey :: (k -> v -> v -> v) -> OMap k v -> OMap k v -> OMap k v
unionWithKey k -> v -> v -> v
f = (OMap k v -> OMap k v -> OMap k v)
-> OMap k v -> OMap k v -> OMap k v
coerce ((k -> v -> v -> v) -> OMap k v -> OMap k v -> OMap k v
forall k v.
Ord k =>
(k -> v -> v -> v) -> OMap k v -> OMap k v -> OMap k v
OM.unionWithL k -> v -> v -> v
f)

delete :: forall k v. Ord k => k -> OMap k v -> OMap k v
delete :: k -> OMap k v -> OMap k v
delete = (k -> OMap k v -> OMap k v) -> k -> OMap k v -> OMap k v
coerce (k -> OMap k v -> OMap k v
forall k v. Ord k => k -> OMap k v -> OMap k v
OM.delete :: k -> OM.OMap k v -> OM.OMap k v)

filterWithKey :: Ord k => (k -> v -> Bool) -> OMap k v -> OMap k v
filterWithKey :: (k -> v -> Bool) -> OMap k v -> OMap k v
filterWithKey k -> v -> Bool
f = (OMap k v -> OMap k v) -> OMap k v -> OMap k v
coerce ((k -> v -> Bool) -> OMap k v -> OMap k v
forall k v. Ord k => (k -> v -> Bool) -> OMap k v -> OMap k v
OM.filter k -> v -> Bool
f)

(\\) :: forall k v v'. Ord k => OMap k v -> OMap k v' -> OMap k v
\\ :: OMap k v -> OMap k v' -> OMap k v
(\\) = (OMap k v -> OMap k v' -> OMap k v)
-> OMap k v -> OMap k v' -> OMap k v
coerce (OMap k v -> OMap k v' -> OMap k v
forall k v v'. Ord k => OMap k v -> OMap k v' -> OMap k v
(OM.\\) :: OM.OMap k v -> OM.OMap k v' -> OM.OMap k v)

intersection :: forall k v v'. Ord k => OMap k v -> OMap k v' -> OMap k v
intersection :: OMap k v -> OMap k v' -> OMap k v
intersection = (OMap k v -> OMap k v' -> OMap k v)
-> OMap k v -> OMap k v' -> OMap k v
coerce (OMap k v -> OMap k v' -> OMap k v
forall k v v'. Ord k => OMap k v -> OMap k v' -> OMap k v
(OM.|/\) :: OM.OMap k v -> OM.OMap k v' -> OM.OMap k v)

intersectionWithKey :: Ord k => (k -> v -> v' -> v'') -> OMap k v -> OMap k v' -> OMap k v''
intersectionWithKey :: (k -> v -> v' -> v'') -> OMap k v -> OMap k v' -> OMap k v''
intersectionWithKey k -> v -> v' -> v''
f = (OMap k v -> OMap k v' -> OMap k v'')
-> OMap k v -> OMap k v' -> OMap k v''
coerce ((k -> v -> v' -> v'') -> OMap k v -> OMap k v' -> OMap k v''
forall k v v' v''.
Ord k =>
(k -> v -> v' -> v'') -> OMap k v -> OMap k v' -> OMap k v''
OM.intersectionWith k -> v -> v' -> v''
f)

null :: forall k v. OMap k v -> Bool
null :: OMap k v -> Bool
null = (OMap k v -> Bool) -> OMap k v -> Bool
coerce (OMap k v -> Bool
forall k v. OMap k v -> Bool
OM.null :: OM.OMap k v -> Bool)

size :: forall k v. OMap k v -> Int
size :: OMap k v -> Int
size = (OMap k v -> Int) -> OMap k v -> Int
coerce (OMap k v -> Int
forall k v. OMap k v -> Int
OM.size :: OM.OMap k v -> Int)

member :: forall k v. Ord k => k -> OMap k v -> Bool
member :: k -> OMap k v -> Bool
member = (k -> OMap k v -> Bool) -> k -> OMap k v -> Bool
coerce (k -> OMap k v -> Bool
forall k v. Ord k => k -> OMap k v -> Bool
OM.member :: k -> OM.OMap k v -> Bool)

notMember :: forall k v. Ord k => k -> OMap k v -> Bool
notMember :: k -> OMap k v -> Bool
notMember = (k -> OMap k v -> Bool) -> k -> OMap k v -> Bool
coerce (k -> OMap k v -> Bool
forall k v. Ord k => k -> OMap k v -> Bool
OM.notMember :: k -> OM.OMap k v -> Bool)

lookup :: forall k v. Ord k => k -> OMap k v -> Maybe v
lookup :: k -> OMap k v -> Maybe v
lookup = (k -> OMap k v -> Maybe v) -> k -> OMap k v -> Maybe v
coerce (k -> OMap k v -> Maybe v
forall k v. Ord k => k -> OMap k v -> Maybe v
OM.lookup :: k -> OM.OMap k v -> Maybe v)

lookupIndex :: forall k v. Ord k => k -> OMap k v -> Maybe Index
lookupIndex :: k -> OMap k v -> Maybe Int
lookupIndex = (k -> OMap k v -> Maybe Int) -> k -> OMap k v -> Maybe Int
coerce (k -> OMap k v -> Maybe Int
forall k v. Ord k => k -> OMap k v -> Maybe Int
OM.findIndex :: k -> OM.OMap k v -> Maybe Index)

lookupAt :: forall k v. Index -> OMap k v -> Maybe (k, v)
lookupAt :: Int -> OMap k v -> Maybe (k, v)
lookupAt Int
i OMap k v
m = Maybe (k, v) -> Maybe (k, v)
coerce (OMap k v -> Int -> Maybe (k, v)
forall k v. OMap k v -> Int -> Maybe (k, v)
OM.elemAt (OMap k v -> OMap k v
coerce OMap k v
m) Int
i :: Maybe (k, v))

fromList :: Ord k => [(k, v)] -> OMap k v
fromList :: [(k, v)] -> OMap k v
fromList [(k, v)]
l = OMap k v -> OMap k v
coerce ([(k, v)] -> OMap k v
forall k v. Ord k => [(k, v)] -> OMap k v
OM.fromList [(k, v)]
l)

assocs :: forall k v. OMap k v -> [(k, v)]
assocs :: OMap k v -> [(k, v)]
assocs = (OMap k v -> [(k, v)]) -> OMap k v -> [(k, v)]
coerce (OMap k v -> [(k, v)]
forall k v. OMap k v -> [(k, v)]
OM.assocs :: OM.OMap k v -> [(k, v)])

toAscList :: forall k v. OMap k v -> [(k, v)]
toAscList :: OMap k v -> [(k, v)]
toAscList = (OMap k v -> [(k, v)]) -> OMap k v -> [(k, v)]
coerce (OMap k v -> [(k, v)]
forall k v. OMap k v -> [(k, v)]
OM.toAscList :: OM.OMap k v -> [(k, v)])

toMap :: forall k v. OMap k v -> M.Map k v
toMap :: OMap k v -> Map k v
toMap = (OMap k v -> Map k v) -> OMap k v -> Map k v
coerce (OMap k v -> Map k v
forall k v. OMap k v -> Map k v
OM.toMap :: OM.OMap k v -> M.Map k v)