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

{-# OPTIONS_GHC -O2 #-}

module Data.Set.Unlifted
  ( S.Set
  , empty
  , singleton
  , null
  , member
  , size
  , difference
  , intersection
  , intersects
  , subset
  , enumFromTo
    -- * Conversion
  , toArray
  , S.toList
  , S.fromList
    -- * Folds
  , foldr
  , foldMap
  , foldl'
  , foldr'
  , foldMap'
    -- * Traversals
  , traverse_
  , itraverse_
  ) where

import Prelude hiding (foldr,foldMap,null,enumFromTo)

import Data.Primitive.Unlifted.Array (UnliftedArray)
import Data.Primitive.Unlifted.Class (PrimUnlifted)
import Data.Semigroup (Semigroup)
import Data.Set.Unlifted.Internal (Set(..))
import qualified Data.Set.Internal as I
import qualified Data.Set.Unlifted.Internal as S

-- | Test for membership in the set.
member :: (PrimUnlifted a, Ord a) => a -> Set a -> Bool
member :: forall a. (PrimUnlifted a, Ord a) => a -> Set a -> Bool
member a
a (Set Set UnliftedArray a
s) = forall (arr :: * -> *) a.
(Contiguous arr, Element arr a, Ord a) =>
a -> Set arr a -> Bool
I.member a
a Set UnliftedArray a
s

-- | The empty set.
empty :: Set a
empty :: forall a. Set a
empty = forall a. Set UnliftedArray a -> Set a
Set forall (arr :: * -> *) a. Contiguous arr => Set arr a
I.empty

-- | True if the set is empty
null :: Set a -> Bool
null :: forall a. Set a -> Bool
null (Set Set UnliftedArray a
s) = forall (arr :: * -> *) a. Contiguous arr => Set arr a -> Bool
I.null Set UnliftedArray a
s

-- | Construct a set with a single element.
singleton :: PrimUnlifted a => a -> Set a
singleton :: forall a. PrimUnlifted a => a -> Set a
singleton = forall a. Set UnliftedArray a -> Set a
Set forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (arr :: * -> *) a.
(Contiguous arr, Element arr a) =>
a -> Set arr a
I.singleton

-- | The number of elements in the set.
size :: PrimUnlifted a => Set a -> Int
size :: forall a. PrimUnlifted a => Set a -> Int
size (Set Set UnliftedArray a
s) = forall (arr :: * -> *) a.
(Contiguous arr, Element arr a) =>
Set arr a -> Int
I.size Set UnliftedArray a
s

-- | The difference of two sets.
difference :: (PrimUnlifted a, Ord a) => Set a -> Set a -> Set a
difference :: forall a. (PrimUnlifted a, Ord a) => Set a -> Set a -> Set a
difference (Set Set UnliftedArray a
x) (Set Set UnliftedArray a
y) = forall a. Set UnliftedArray a -> Set a
Set (forall a (arr :: * -> *).
(ContiguousU arr, Element arr a, Ord a) =>
Set arr a -> Set arr a -> Set arr a
I.difference Set UnliftedArray a
x Set UnliftedArray a
y)

-- | The intersection of two sets.
intersection :: (Ord a, PrimUnlifted a) => Set a -> Set a -> Set a
intersection :: forall a. (Ord a, PrimUnlifted a) => Set a -> Set a -> Set a
intersection (Set Set UnliftedArray a
x) (Set Set UnliftedArray a
y) = forall a. Set UnliftedArray a -> Set a
Set (forall a (arr :: * -> *).
(ContiguousU arr, Element arr a, Ord a) =>
Set arr a -> Set arr a -> Set arr a
I.intersection Set UnliftedArray a
x Set UnliftedArray a
y)

-- | Do the two sets contain any of the same elements?
intersects :: (Ord a, PrimUnlifted a) => Set a -> Set a -> Bool
intersects :: forall a. (Ord a, PrimUnlifted a) => Set a -> Set a -> Bool
intersects (Set Set UnliftedArray a
x) (Set Set UnliftedArray a
y) = forall a (arr :: * -> *).
(Contiguous arr, Element arr a, Ord a) =>
Set arr a -> Set arr a -> Bool
I.intersects Set UnliftedArray a
x Set UnliftedArray a
y

-- | Is the first argument a subset of the second argument?
subset :: (Ord a, PrimUnlifted a) => Set a -> Set a -> Bool
subset :: forall a. (Ord a, PrimUnlifted a) => Set a -> Set a -> Bool
subset (Set Set UnliftedArray a
x) (Set Set UnliftedArray a
y) = forall (arr :: * -> *) a.
(Contiguous arr, Element arr a, Ord a) =>
Set arr a -> Set arr a -> Bool
I.subset Set UnliftedArray a
x Set UnliftedArray a
y

-- | The set that includes all elements from the lower bound to the
-- upper bound.
enumFromTo :: (Enum a, Ord a, Num a, PrimUnlifted a)
  => a -- ^ Inclusive lower bound
  -> a -- ^ Inclusive upper bound
  -> Set a
enumFromTo :: forall a. (Enum a, Ord a, Num a, PrimUnlifted a) => a -> a -> Set a
enumFromTo a
lo a
hi = forall a. Set UnliftedArray a -> Set a
Set (forall (arr :: * -> *) a.
(Contiguous arr, Element arr a, Enum a, Ord a, Num a) =>
a -> a -> Set arr a
I.enumFromTo a
lo a
hi)

-- | /O(1)/ Convert a set to an array. The elements are given in ascending
-- order. This function is zero-cost.
toArray :: Set a -> UnliftedArray a
toArray :: forall a. Set a -> UnliftedArray a
toArray (Set Set UnliftedArray a
s) = forall (arr :: * -> *) a. Set arr a -> arr a
I.toArray Set UnliftedArray a
s

-- | Right fold over the elements in the set. This is lazy in the accumulator.
foldr :: PrimUnlifted a
  => (a -> b -> b)
  -> b
  -> Set a
  -> b
foldr :: forall a b. PrimUnlifted a => (a -> b -> b) -> b -> Set a -> b
foldr a -> b -> b
f b
b0 (Set Set UnliftedArray a
s) = forall (arr :: * -> *) a b.
(Contiguous arr, Element arr a) =>
(a -> b -> b) -> b -> Set arr a -> b
I.foldr a -> b -> b
f b
b0 Set UnliftedArray a
s

-- | Monoidal fold over the elements in the set. This is lazy in the accumulator.
foldMap :: (PrimUnlifted a, Monoid m)
  => (a -> m)
  -> Set a
  -> m
foldMap :: forall a m. (PrimUnlifted a, Monoid m) => (a -> m) -> Set a -> m
foldMap a -> m
f (Set Set UnliftedArray a
s) = forall (arr :: * -> *) a m.
(Contiguous arr, Element arr a, Monoid m) =>
(a -> m) -> Set arr a -> m
I.foldMap a -> m
f Set UnliftedArray a
s

-- | Strict left fold over the elements in the set.
foldl' :: PrimUnlifted a
  => (b -> a -> b)
  -> b
  -> Set a
  -> b
foldl' :: forall a b. PrimUnlifted a => (b -> a -> b) -> b -> Set a -> b
foldl' b -> a -> b
f b
b0 (Set Set UnliftedArray a
s) = forall (arr :: * -> *) a b.
(Contiguous arr, Element arr a) =>
(b -> a -> b) -> b -> Set arr a -> b
I.foldl' b -> a -> b
f b
b0 Set UnliftedArray a
s

-- | Strict right fold over the elements in the set.
foldr' :: PrimUnlifted a
  => (a -> b -> b)
  -> b
  -> Set a
  -> b
foldr' :: forall a b. PrimUnlifted a => (a -> b -> b) -> b -> Set a -> b
foldr' a -> b -> b
f b
b0 (Set Set UnliftedArray a
s) = forall (arr :: * -> *) a b.
(Contiguous arr, Element arr a) =>
(a -> b -> b) -> b -> Set arr a -> b
I.foldr' a -> b -> b
f b
b0 Set UnliftedArray a
s

-- | Strict monoidal fold over the elements in the set.
foldMap' :: (PrimUnlifted a, Monoid m)
  => (a -> m)
  -> Set a
  -> m
foldMap' :: forall a m. (PrimUnlifted a, Monoid m) => (a -> m) -> Set a -> m
foldMap' a -> m
f (Set Set UnliftedArray a
arr) = forall (arr :: * -> *) a m.
(Contiguous arr, Element arr a, Monoid m) =>
(a -> m) -> Set arr a -> m
I.foldMap' a -> m
f Set UnliftedArray a
arr

-- | Traverse a set, discarding the result.
traverse_ :: (Applicative m, PrimUnlifted a)
  => (a -> m b)
  -> Set a
  -> m ()
traverse_ :: forall (m :: * -> *) a b.
(Applicative m, PrimUnlifted a) =>
(a -> m b) -> Set a -> m ()
traverse_ a -> m b
f (Set Set UnliftedArray a
arr) = forall (arr :: * -> *) a (m :: * -> *) b.
(Contiguous arr, Element arr a, Applicative m) =>
(a -> m b) -> Set arr a -> m ()
I.traverse_ a -> m b
f Set UnliftedArray a
arr

-- | Traverse a set with the indices, discarding the result.
itraverse_ :: (Applicative m, PrimUnlifted a)
  => (Int -> a -> m b)
  -> Set a
  -> m ()
itraverse_ :: forall (m :: * -> *) a b.
(Applicative m, PrimUnlifted a) =>
(Int -> a -> m b) -> Set a -> m ()
itraverse_ Int -> a -> m b
f (Set Set UnliftedArray a
arr) = forall (arr :: * -> *) a (m :: * -> *) b.
(Contiguous arr, Element arr a, Applicative m) =>
(Int -> a -> m b) -> Set arr a -> m ()
I.itraverse_ Int -> a -> m b
f Set UnliftedArray a
arr