{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE StandaloneDeriving #-}

module Language.REST.Internal.EquivalenceClass
    ( isMember
    , isSingleton
    , insert
    , union
    , singleton
    , fromList
    , toList
    , head
    , EquivalenceClass
    , elems
    , isSubsetOf
    ) where

import GHC.Generics (Generic)
import Data.Hashable
import qualified Data.Set as S
import qualified Data.List as L
import Prelude hiding (head)

import Language.REST.Types () -- Hashable (S.Set a)

-- | Equivalent classes of the @(==)@ relation of a type @a@.
newtype EquivalenceClass a =
  -- | The set contains all of the elements of the class
  EquivalenceClass (S.Set a)
#if MIN_VERSION_hashable(1,3,5)
  deriving (EquivalenceClass a -> EquivalenceClass a -> Bool
EquivalenceClass a -> EquivalenceClass a -> Ordering
EquivalenceClass a -> EquivalenceClass a -> EquivalenceClass a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (EquivalenceClass a)
forall a. Ord a => EquivalenceClass a -> EquivalenceClass a -> Bool
forall a.
Ord a =>
EquivalenceClass a -> EquivalenceClass a -> Ordering
forall a.
Ord a =>
EquivalenceClass a -> EquivalenceClass a -> EquivalenceClass a
min :: EquivalenceClass a -> EquivalenceClass a -> EquivalenceClass a
$cmin :: forall a.
Ord a =>
EquivalenceClass a -> EquivalenceClass a -> EquivalenceClass a
max :: EquivalenceClass a -> EquivalenceClass a -> EquivalenceClass a
$cmax :: forall a.
Ord a =>
EquivalenceClass a -> EquivalenceClass a -> EquivalenceClass a
>= :: EquivalenceClass a -> EquivalenceClass a -> Bool
$c>= :: forall a. Ord a => EquivalenceClass a -> EquivalenceClass a -> Bool
> :: EquivalenceClass a -> EquivalenceClass a -> Bool
$c> :: forall a. Ord a => EquivalenceClass a -> EquivalenceClass a -> Bool
<= :: EquivalenceClass a -> EquivalenceClass a -> Bool
$c<= :: forall a. Ord a => EquivalenceClass a -> EquivalenceClass a -> Bool
< :: EquivalenceClass a -> EquivalenceClass a -> Bool
$c< :: forall a. Ord a => EquivalenceClass a -> EquivalenceClass a -> Bool
compare :: EquivalenceClass a -> EquivalenceClass a -> Ordering
$ccompare :: forall a.
Ord a =>
EquivalenceClass a -> EquivalenceClass a -> Ordering
Ord, EquivalenceClass a -> EquivalenceClass a -> Bool
forall a. Eq a => EquivalenceClass a -> EquivalenceClass a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EquivalenceClass a -> EquivalenceClass a -> Bool
$c/= :: forall a. Eq a => EquivalenceClass a -> EquivalenceClass a -> Bool
== :: EquivalenceClass a -> EquivalenceClass a -> Bool
$c== :: forall a. Eq a => EquivalenceClass a -> EquivalenceClass a -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (EquivalenceClass a) x -> EquivalenceClass a
forall a x. EquivalenceClass a -> Rep (EquivalenceClass a) x
$cto :: forall a x. Rep (EquivalenceClass a) x -> EquivalenceClass a
$cfrom :: forall a x. EquivalenceClass a -> Rep (EquivalenceClass a) x
Generic, forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
forall {a}. Hashable a => Eq (EquivalenceClass a)
forall a. Hashable a => Int -> EquivalenceClass a -> Int
forall a. Hashable a => EquivalenceClass a -> Int
hash :: EquivalenceClass a -> Int
$chash :: forall a. Hashable a => EquivalenceClass a -> Int
hashWithSalt :: Int -> EquivalenceClass a -> Int
$chashWithSalt :: forall a. Hashable a => Int -> EquivalenceClass a -> Int
Hashable)
#else
  deriving (Ord, Eq, Generic)
#endif

#if !MIN_VERSION_hashable(1,3,5)
deriving instance Hashable (S.Set a) => Hashable (EquivalenceClass a)
#endif

instance Show a => Show (EquivalenceClass a) where
    show :: EquivalenceClass a -> String
show (EquivalenceClass Set a
xs) = forall a. [a] -> [[a]] -> [a]
L.intercalate String
" = " (forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> String
show (forall a. Set a -> [a]
S.toList Set a
xs)) 



{-# INLINE isSubsetOf #-}
isSubsetOf :: Ord a => EquivalenceClass a -> EquivalenceClass a -> Bool
isSubsetOf :: forall a. Ord a => EquivalenceClass a -> EquivalenceClass a -> Bool
isSubsetOf (EquivalenceClass Set a
xs) (EquivalenceClass Set a
ys) = Set a
xs forall a. Ord a => Set a -> Set a -> Bool
`S.isSubsetOf` Set a
ys

head :: EquivalenceClass a -> a
head :: forall a. EquivalenceClass a -> a
head (EquivalenceClass Set a
xs) = forall a. [a] -> a
L.head forall a b. (a -> b) -> a -> b
$ forall a. Set a -> [a]
S.toList Set a
xs

isSingleton :: EquivalenceClass a -> Bool
isSingleton :: forall a. EquivalenceClass a -> Bool
isSingleton (EquivalenceClass Set a
xs) = forall a. Set a -> Int
S.size Set a
xs forall a. Eq a => a -> a -> Bool
== Int
1

{-# INLINE isMember #-}
isMember :: (Ord a, Eq a, Hashable a) => a -> EquivalenceClass a -> Bool
isMember :: forall a.
(Ord a, Eq a, Hashable a) =>
a -> EquivalenceClass a -> Bool
isMember a
x (EquivalenceClass Set a
xs) = forall a. Ord a => a -> Set a -> Bool
S.member a
x Set a
xs

insert :: (Ord a, Eq a, Hashable a) => a -> EquivalenceClass a -> EquivalenceClass a
insert :: forall a.
(Ord a, Eq a, Hashable a) =>
a -> EquivalenceClass a -> EquivalenceClass a
insert a
x (EquivalenceClass Set a
xs) = forall a. Set a -> EquivalenceClass a
EquivalenceClass (forall a. Ord a => a -> Set a -> Set a
S.insert a
x Set a
xs)

union :: (Ord a, Eq a, Hashable a) => EquivalenceClass a -> EquivalenceClass a -> EquivalenceClass a
union :: forall a.
(Ord a, Eq a, Hashable a) =>
EquivalenceClass a -> EquivalenceClass a -> EquivalenceClass a
union (EquivalenceClass Set a
xs) (EquivalenceClass Set a
ys) = 
    forall a. Set a -> EquivalenceClass a
EquivalenceClass (forall a. Ord a => Set a -> Set a -> Set a
S.union Set a
xs Set a
ys)

singleton :: (Ord a, Eq a, Hashable a) => a -> EquivalenceClass a
singleton :: forall a. (Ord a, Eq a, Hashable a) => a -> EquivalenceClass a
singleton = forall a. Set a -> EquivalenceClass a
EquivalenceClass forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Set a
S.singleton

fromList :: (Ord a, Eq a, Hashable a) => [a] -> EquivalenceClass a
fromList :: forall a. (Ord a, Eq a, Hashable a) => [a] -> EquivalenceClass a
fromList = forall a. Set a -> EquivalenceClass a
EquivalenceClass forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> Set a
S.fromList

toList :: EquivalenceClass a -> [a]
toList :: forall a. EquivalenceClass a -> [a]
toList (EquivalenceClass Set a
s) = forall a. Set a -> [a]
S.toList Set a
s

{-# INLINE elems #-}
elems :: EquivalenceClass a -> S.Set a
elems :: forall a. EquivalenceClass a -> Set a
elems (EquivalenceClass Set a
ec) = Set a
ec