    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE TypeApplications #-}

    -----------------------------------------------------------------------------
    -- |
    -- 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 :: forall k v. OMap k v
    empty = OMap k v -> OMap k v
    forall a b. Coercible a b => a -> b
    coerce (forall k v. OMap k v
    OM.empty @k @v)

    singleton :: k -> v -> OMap k v
    singleton :: forall k v. k -> v -> OMap k v
    singleton k
    k v
    v = OMap k v -> OMap k v
    forall a b. Coercible a b => a -> b
    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 :: forall k v. Ord k => 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
    forall a b. Coercible a b => a -> b
    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 :: forall k v. Ord k => OMap k v -> k -> v -> OMap k v
    insertPost OMap k v
    m k
    k v
    v = OMap k v -> OMap k v
    forall a b. Coercible a b => a -> b
    coerce (OMap k v -> OMap k v
    forall a b. Coercible a b => a -> b
    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 :: forall k v. Ord k => 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
    forall a b. Coercible a b => a -> b
    coerce (forall k v. Ord k => OMap k v -> OMap k v -> OMap k v
    (OM.|<>) @k @v)

    unionWithKey :: Ord k => (k -> v -> v -> v) -> OMap k v -> OMap k v -> OMap k v
    unionWithKey :: forall k v.
    Ord k =>
    (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
    forall a b. Coercible a b => a -> b
    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 :: forall k v. Ord k => k -> OMap k v -> OMap k v
    delete = (k -> OMap k v -> OMap k v) -> k -> OMap k v -> OMap k v
    forall a b. Coercible a b => a -> b
    coerce (forall k v. Ord k => k -> OMap k v -> OMap k v
    OM.delete @k @v)

    filterWithKey :: Ord k => (k -> v -> Bool) -> OMap k v -> OMap k v
    filterWithKey :: forall k v. Ord k => (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
    forall a b. Coercible a b => a -> b
    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
    \\ :: 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
    forall a b. Coercible a b => a -> b
    coerce (forall k v v'. Ord k => OMap k v -> OMap k v' -> OMap k v
    (OM.\\) @k @v @v')

    intersection :: forall k v v'. Ord k => OMap k v -> OMap k v' -> 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)
    -> OMap k v -> OMap k v' -> OMap k v
    forall a b. Coercible a b => a -> b
    coerce (forall k v v'. Ord k => OMap k v -> OMap k v' -> OMap k v
    (OM.|/\) @k @v @v')

    intersectionWithKey :: Ord k => (k -> v -> v' -> v'') -> OMap k v -> OMap k v' -> OMap k v''
    intersectionWithKey :: forall k v v' v''.
    Ord k =>
    (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''
    forall a b. Coercible a b => a -> b
    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 :: forall k v. OMap k v -> Bool
    null = (OMap k v -> Bool) -> OMap k v -> Bool
    forall a b. Coercible a b => a -> b
    coerce (forall k v. OMap k v -> Bool
    OM.null @k @v)

    size :: forall k v. OMap k v -> Int
    size :: forall k v. OMap k v -> Int
    size = (OMap k v -> Int) -> OMap k v -> Int
    forall a b. Coercible a b => a -> b
    coerce (forall k v. OMap k v -> Int
    OM.size @k @v)

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

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

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

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

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

    fromList :: Ord k => [(k, v)] -> OMap k v
    fromList :: forall k v. Ord k => [(k, v)] -> OMap k v
    fromList [(k, v)]
    l = OMap k v -> OMap k v
    forall a b. Coercible a b => a -> b
    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 :: forall k v. OMap k v -> [(k, v)]
    assocs = (OMap k v -> [(k, v)]) -> OMap k v -> [(k, v)]
    forall a b. Coercible a b => a -> b
    coerce (forall k v. OMap k v -> [(k, v)]
    OM.assocs @k @v)

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

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