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

module Data.Set.Lifted.Internal
  ( Set(..)
  , toList
  , fromList
  , foldr
  , foldl'
  , foldr'
  ) where

import Prelude hiding (foldr)

import Data.Functor.Classes (Eq1(liftEq),Show1(liftShowsPrec))
import Data.Hashable (Hashable)
import Data.Hashable.Lifted (Hashable1)
import Data.Primitive (Array)
import Data.Semigroup (Semigroup)
import Text.Show (showListWith)

import qualified Data.Foldable as F
import qualified Data.Hashable as H
import qualified Data.Hashable.Lifted as HL
import qualified Data.Semigroup as SG
import qualified Data.Set.Internal as I
import qualified GHC.Exts as E

newtype Set a = Set { forall a. Set a -> Set Array a
getSet :: I.Set Array a }

instance F.Foldable Set where
  foldr :: forall a b. (a -> b -> b) -> b -> Set a -> b
foldr = forall a b. (a -> b -> b) -> b -> Set a -> b
foldr
  foldl' :: forall b a. (b -> a -> b) -> b -> Set a -> b
foldl' = forall b a. (b -> a -> b) -> b -> Set a -> b
foldl'
  foldr' :: forall a b. (a -> b -> b) -> b -> Set a -> b
foldr' = forall a b. (a -> b -> b) -> b -> Set a -> b
foldr'

instance Ord a => Semigroup (Set a) where
  Set Set Array a
x <> :: Set a -> Set a -> Set a
<> Set Set Array a
y = forall a. Set Array a -> Set a
Set (forall (arr :: * -> *) a.
(ContiguousU arr, Element arr a, Ord a) =>
Set arr a -> Set arr a -> Set arr a
I.append Set Array a
x Set Array a
y)
  stimes :: forall b. Integral b => b -> Set a -> Set a
stimes = forall b a. (Integral b, Monoid a) => b -> a -> a
SG.stimesIdempotentMonoid
  sconcat :: NonEmpty (Set a) -> Set a
sconcat NonEmpty (Set a)
xs = forall a. Set Array a -> Set a
Set (forall (arr :: * -> *) a.
(ContiguousU arr, Element arr a, Ord a) =>
[Set arr a] -> Set arr a
I.concat (coerce :: forall a b. Coercible a b => a -> b
E.coerce (forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList NonEmpty (Set a)
xs)))

instance Ord a => Monoid (Set a) where
  mempty :: Set a
mempty = forall a. Set Array a -> Set a
Set forall (arr :: * -> *) a. Contiguous arr => Set arr a
I.empty
  mappend :: Set a -> Set a -> Set a
mappend = forall a. Semigroup a => a -> a -> a
(SG.<>)
  mconcat :: [Set a] -> Set a
mconcat [Set a]
xs = forall a. Set Array a -> Set a
Set (forall (arr :: * -> *) a.
(ContiguousU arr, Element arr a, Ord a) =>
[Set arr a] -> Set arr a
I.concat (coerce :: forall a b. Coercible a b => a -> b
E.coerce [Set a]
xs))

instance Eq a => Eq (Set a) where
  Set Set Array a
x == :: Set a -> Set a -> Bool
== Set Set Array a
y = forall (arr :: * -> *) a.
(Contiguous arr, Element arr a, Eq a) =>
Set arr a -> Set arr a -> Bool
I.equals Set Array a
x Set Array a
y

instance Eq1 Set where
  liftEq :: forall a b. (a -> b -> Bool) -> Set a -> Set b -> Bool
liftEq a -> b -> Bool
f Set a
a Set b
b = forall (f :: * -> *) a b.
Eq1 f =>
(a -> b -> Bool) -> f a -> f b -> Bool
liftEq a -> b -> Bool
f (forall a. Set a -> [a]
toList Set a
a) (forall a. Set a -> [a]
toList Set b
b)

instance Ord a => Ord (Set a) where
  compare :: Set a -> Set a -> Ordering
compare (Set Set Array a
x) (Set Set Array a
y) = forall (arr :: * -> *) a.
(Contiguous arr, Element arr a, Ord a) =>
Set arr a -> Set arr a -> Ordering
I.compare Set Array a
x Set Array a
y

instance Ord a => E.IsList (Set a) where
  type Item (Set a) = a
  fromListN :: Int -> [Item (Set a)] -> Set a
fromListN Int
n = forall a. Set Array a -> Set a
Set forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (arr :: * -> *) a.
(ContiguousU arr, Element arr a, Ord a) =>
Int -> [a] -> Set arr a
I.fromListN Int
n
  fromList :: [Item (Set a)] -> Set a
fromList = forall a. Set Array a -> Set a
Set forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (arr :: * -> *) a.
(ContiguousU arr, Element arr a, Ord a) =>
[a] -> Set arr a
I.fromList
  toList :: Set a -> [Item (Set a)]
toList = forall a. Set a -> [a]
toList

instance Show a => Show (Set a) where
  showsPrec :: Int -> Set a -> ShowS
showsPrec Int
p (Set Set Array a
s) = forall (arr :: * -> *) a.
(Contiguous arr, Element arr a, Show a) =>
Int -> Set arr a -> ShowS
I.showsPrec Int
p Set Array a
s

instance Show1 Set where
  liftShowsPrec :: forall a.
(Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Set a -> ShowS
liftShowsPrec Int -> a -> ShowS
f [a] -> ShowS
_ Int
p Set a
s = Bool -> ShowS -> ShowS
showParen (Int
p forall a. Ord a => a -> a -> Bool
> Int
10) forall a b. (a -> b) -> a -> b
$
   String -> ShowS
showString String
"fromList " forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> ShowS) -> [a] -> ShowS
showListWith (Int -> a -> ShowS
f Int
0) (forall a. Set a -> [a]
toList Set a
s)

instance Hashable1 Set where
  liftHashWithSalt :: forall a. (Int -> a -> Int) -> Int -> Set a -> Int
liftHashWithSalt Int -> a -> Int
f Int
s (Set Set Array a
arr) = forall (arr :: * -> *) a.
(Contiguous arr, Element arr a) =>
(Int -> a -> Int) -> Int -> Set arr a -> Int
I.liftHashWithSalt Int -> a -> Int
f Int
s Set Array a
arr

instance Hashable a => Hashable (Set a) where
  hashWithSalt :: Int -> Set a -> Int
hashWithSalt = forall (f :: * -> *) a.
(Hashable1 f, Hashable a) =>
Int -> f a -> Int
HL.hashWithSalt1

-- | Convert a set to a list. The elements are given in ascending order.
toList :: Set a -> [a]
toList :: forall a. Set a -> [a]
toList (Set Set Array a
s) = forall (arr :: * -> *) a.
(Contiguous arr, Element arr a) =>
Set arr a -> [a]
I.toList Set Array a
s

-- | Convert a list to a set.
fromList :: Ord a => [a] -> Set a
fromList :: forall a. Ord a => [a] -> Set a
fromList = forall a. Set Array a -> Set a
Set forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (arr :: * -> *) a.
(ContiguousU arr, Element arr a, Ord a) =>
[a] -> Set arr a
I.fromList

-- | Right fold over the elements in the set. This is lazy in the accumulator.
foldr :: 
     (a -> b -> b)
  -> b
  -> Set a
  -> b
foldr :: forall a b. (a -> b -> b) -> b -> Set a -> b
foldr a -> b -> b
f b
b0 (Set Set Array 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 Array a
s

-- | Strict left fold over the elements in the set.
foldl' :: 
     (b -> a -> b)
  -> b
  -> Set a
  -> b
foldl' :: forall b a. (b -> a -> b) -> b -> Set a -> b
foldl' b -> a -> b
f b
b0 (Set Set Array 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 Array a
s

-- | Strict right fold over the elements in the set.
foldr' :: 
     (a -> b -> b)
  -> b
  -> Set a
  -> b
foldr' :: forall a b. (a -> b -> b) -> b -> Set a -> b
foldr' a -> b -> b
f b
b0 (Set Set Array 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 Array a
s