{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}

{-# OPTIONS_GHC -O2 #-}
module Data.Diet.Map.Strict.Unboxed.Lifted
  ( Map
  , empty
  , singleton
  , lookup
  , mapBijection
    -- * List Conversion
  , fromList
  , fromListAppend
  , fromListN
  , fromListAppendN
  ) where

import Prelude hiding (lookup,map)

import Data.Functor.Classes (Show2(..))
import Data.Primitive.Array (Array)
import Data.Primitive.PrimArray (PrimArray)
import Data.Primitive.Types (Prim)
import Data.Semigroup (Semigroup)
import qualified GHC.Exts as E
import qualified Data.Semigroup as SG
import qualified Data.Diet.Map.Strict.Internal as I

newtype Map k v = Map (I.Map PrimArray Array k v)

-- | The empty diet map.
empty :: Map k v
empty :: forall k v. Map k v
empty = forall k v. Map PrimArray Array k v -> Map k v
Map forall (karr :: * -> *) (varr :: * -> *) k v.
(ContiguousU karr, ContiguousU varr) =>
Map karr varr k v
I.empty

-- | /O(1)/ Create a diet map with a single element.
singleton :: (Prim k,Ord k)
  => k -- ^ inclusive lower bound
  -> k -- ^ inclusive upper bound
  -> v -- ^ value
  -> Map k v
singleton :: forall k v. (Prim k, Ord k) => k -> k -> v -> Map k v
singleton k
lo k
hi v
v = forall k v. Map PrimArray Array k v -> Map k v
Map (forall (karr :: * -> *) (varr :: * -> *) k v.
(ContiguousU karr, Element karr k, Ord k, ContiguousU varr,
 Element varr v) =>
k -> k -> v -> Map karr varr k v
I.singleton k
lo k
hi v
v)

-- | /O(log n)/ Lookup the value at a key in the map.
lookup :: (Prim k, Ord k) => k -> Map k v -> Maybe v
lookup :: forall k v. (Prim k, Ord k) => k -> Map k v -> Maybe v
lookup k
a (Map Map PrimArray Array k v
s) = forall (karr :: * -> *) (varr :: * -> *) k v.
(ContiguousU karr, Element karr k, Ord k, ContiguousU varr,
 Element varr v) =>
k -> Map karr varr k v -> Maybe v
I.lookup k
a Map PrimArray Array k v
s

instance (Prim k, Show k, Show v) => Show (Map k v) where
  showsPrec :: Int -> Map k v -> ShowS
showsPrec Int
p (Map Map PrimArray Array k v
m) = forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Show k, ContiguousU varr,
 Element varr v, Show v) =>
Int -> Map karr varr k v -> ShowS
I.showsPrec Int
p Map PrimArray Array k v
m

instance (Prim k, Eq k, Eq v) => Eq (Map k v) where
  Map Map PrimArray Array k v
x == :: Map k v -> Map k v -> Bool
== Map Map PrimArray Array k v
y = forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Eq k, ContiguousU varr,
 Element varr v, Eq v) =>
Map karr varr k v -> Map karr varr k v -> Bool
I.equals Map PrimArray Array k v
x Map PrimArray Array k v
y

instance (Prim k, Ord k, Enum k, Semigroup v, Eq v) => Semigroup (Map k v) where
  Map Map PrimArray Array k v
x <> :: Map k v -> Map k v -> Map k v
<> Map Map PrimArray Array k v
y = forall k v. Map PrimArray Array k v -> Map k v
Map (forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Ord k, Enum k, ContiguousU varr,
 Element varr v, Semigroup v, Eq v) =>
Map karr varr k v -> Map karr varr k v -> Map karr varr k v
I.append Map PrimArray Array k v
x Map PrimArray Array k v
y)

instance (Prim k, Ord k, Enum k, Semigroup v, Eq v) => Monoid (Map k v) where
  mempty :: Map k v
mempty = forall k v. Map PrimArray Array k v -> Map k v
Map forall (karr :: * -> *) (varr :: * -> *) k v.
(ContiguousU karr, ContiguousU varr) =>
Map karr varr k v
I.empty
  mappend :: Map k v -> Map k v -> Map k v
mappend = forall a. Semigroup a => a -> a -> a
(SG.<>)
  mconcat :: [Map k v] -> Map k v
mconcat = forall k v. Map PrimArray Array k v -> Map k v
Map forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Ord k, Enum k, ContiguousU varr,
 Element varr v, Semigroup v, Eq v) =>
[Map karr varr k v] -> Map karr varr k v
I.concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
E.coerce

instance (Prim k, Ord k, Enum k, Eq v) => E.IsList (Map k v) where
  type Item (Map k v) = (k,k,v)
  fromListN :: Int -> [Item (Map k v)] -> Map k v
fromListN Int
n = forall k v. Map PrimArray Array k v -> Map k v
Map forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Ord k, Enum k, ContiguousU varr,
 Element varr v, Eq v) =>
Int -> [(k, k, v)] -> Map karr varr k v
I.fromListN Int
n
  fromList :: [Item (Map k v)] -> Map k v
fromList = forall k v. Map PrimArray Array k v -> Map k v
Map forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Ord k, Enum k, ContiguousU varr,
 Element varr v, Eq v) =>
[(k, k, v)] -> Map karr varr k v
I.fromList
  toList :: Map k v -> [Item (Map k v)]
toList (Map Map PrimArray Array k v
s) = forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, ContiguousU varr,
 Element varr v) =>
Map karr varr k v -> [(k, k, v)]
I.toList Map PrimArray Array k v
s

fromList :: (Ord k, Enum k, Prim k, Eq v) => [(k,k,v)] -> Map k v
fromList :: forall k v. (Ord k, Enum k, Prim k, Eq v) => [(k, k, v)] -> Map k v
fromList = forall k v. Map PrimArray Array k v -> Map k v
Map forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Ord k, Enum k, ContiguousU varr,
 Element varr v, Eq v) =>
[(k, k, v)] -> Map karr varr k v
I.fromList

fromListN :: (Ord k, Enum k, Prim k, Eq v)
  => Int -- ^ expected size of resulting 'Map'
  -> [(k,k,v)] -- ^ key-value pairs
  -> Map k v
fromListN :: forall k v.
(Ord k, Enum k, Prim k, Eq v) =>
Int -> [(k, k, v)] -> Map k v
fromListN Int
n = forall k v. Map PrimArray Array k v -> Map k v
Map forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Ord k, Enum k, ContiguousU varr,
 Element varr v, Eq v) =>
Int -> [(k, k, v)] -> Map karr varr k v
I.fromListN Int
n

fromListAppend :: (Ord k, Enum k, Prim k, Semigroup v, Eq v) => [(k,k,v)] -> Map k v
fromListAppend :: forall k v.
(Ord k, Enum k, Prim k, Semigroup v, Eq v) =>
[(k, k, v)] -> Map k v
fromListAppend = forall k v. Map PrimArray Array k v -> Map k v
Map forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Ord k, Enum k, ContiguousU varr,
 Element varr v, Semigroup v, Eq v) =>
[(k, k, v)] -> Map karr varr k v
I.fromListAppend

fromListAppendN :: (Ord k, Enum k, Prim k, Semigroup v, Eq v)
  => Int -- ^ expected size of resulting 'Map'
  -> [(k,k,v)] -- ^ key-value pairs
  -> Map k v
fromListAppendN :: forall k v.
(Ord k, Enum k, Prim k, Semigroup v, Eq v) =>
Int -> [(k, k, v)] -> Map k v
fromListAppendN Int
n = forall k v. Map PrimArray Array k v -> Map k v
Map forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (karr :: * -> *) k (varr :: * -> *) v.
(ContiguousU karr, Element karr k, Ord k, Enum k, ContiguousU varr,
 Element varr v, Semigroup v, Eq v) =>
Int -> [(k, k, v)] -> Map karr varr k v
I.fromListAppendN Int
n

-- | Map an equality morphism over the values in a diet map. An bijection
-- @f@ must satisfy the law:
--
-- > ∀ x y. x == y ↔ f x == f y
--
-- Since this does not actually use the 'Eq' constraint on the new value
-- type, it is lazy in the values.
mapBijection :: (Prim k, Ord k)
  => (v -> w) -- ^ bijection
  -> Map k v
  -> Map k w
mapBijection :: forall k v w. (Prim k, Ord k) => (v -> w) -> Map k v -> Map k w
mapBijection v -> w
f (Map Map PrimArray Array k v
m) = forall k v. Map PrimArray Array k v -> Map k v
Map (forall (karr :: * -> *) k (varr :: * -> *) v w.
(ContiguousU karr, Element karr k, ContiguousU varr,
 Element varr v, Element varr w) =>
(v -> w) -> Map karr varr k v -> Map karr varr k w
I.map v -> w
f Map PrimArray Array k v
m)