-- | Provides the 'UniqueSeq' type.
module Charon.Data.UniqueSeq
  ( UniqueSeq (MkUniqueSeq),

    -- * Creation
    empty,
    singleton,
    Internal.fromFoldable,
    fromSet,

    -- * Lookup
    member,
    (∈),
    (∉),

    -- * Operations
    Internal.prepend,
    Internal.append,
    Internal.union,
    (∪),
    (⋃),
    map,
    (↤),
    (↦),

    -- * Display
    displayShow,
    display,
  )
where

import Charon.Data.UniqueSeq.Internal
  ( UniqueSeq
      ( MkUniqueSeq,
        UnsafeUniqueSeq
      ),
  )
import Charon.Data.UniqueSeq.Internal qualified as Internal
import Charon.Prelude
import Data.Foldable (Foldable (toList))
import Data.HashSet qualified as HSet
import Data.Sequence qualified as Seq
import Data.Text qualified as T

empty :: UniqueSeq a
empty :: forall a. UniqueSeq a
empty = Seq a -> HashSet a -> UniqueSeq a
forall a. Seq a -> HashSet a -> UniqueSeq a
UnsafeUniqueSeq Seq a
forall a. Seq a
Seq.empty HashSet a
forall a. HashSet a
HSet.empty

singleton :: (Hashable a) => a -> UniqueSeq a
singleton :: forall a. Hashable a => a -> UniqueSeq a
singleton a
x = Seq a -> HashSet a -> UniqueSeq a
forall a. Seq a -> HashSet a -> UniqueSeq a
UnsafeUniqueSeq (a -> Seq a
forall a. a -> Seq a
Seq.singleton a
x) (a -> HashSet a
forall a. Hashable a => a -> HashSet a
HSet.singleton a
x)

member :: (Hashable a) => a -> UniqueSeq a -> Bool
member :: forall a. Hashable a => a -> UniqueSeq a -> Bool
member a
x (UnsafeUniqueSeq Seq a
_ HashSet a
set) = a -> HashSet a -> Bool
forall a. (Eq a, Hashable a) => a -> HashSet a -> Bool
HSet.member a
x HashSet a
set

map :: (Hashable b) => (a -> b) -> UniqueSeq a -> UniqueSeq b
map :: forall b a. Hashable b => (a -> b) -> UniqueSeq a -> UniqueSeq b
map a -> b
f (UnsafeUniqueSeq Seq a
seq HashSet a
_) = Seq b -> HashSet b -> UniqueSeq b
forall a. Seq a -> HashSet a -> UniqueSeq a
UnsafeUniqueSeq Seq b
newSeq HashSet b
newSet
  where
    (Seq b
newSeq, HashSet b
newSet) = (a -> (Seq b, HashSet b) -> (Seq b, HashSet b))
-> (Seq b, HashSet b) -> Seq a -> (Seq b, HashSet b)
forall a b. (a -> b -> b) -> b -> Seq a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> (Seq b, HashSet b) -> (Seq b, HashSet b)
go (Seq b
forall a. Seq a
Seq.empty, HashSet b
forall a. HashSet a
HSet.empty) Seq a
seq
    go :: a -> (Seq b, HashSet b) -> (Seq b, HashSet b)
go a
x (Seq b
accSeq, HashSet b
accSet)
      | b -> HashSet b -> Bool
forall a. Hashable a => a -> HashSet a -> Bool
Internal.notHSetMember b
y HashSet b
accSet = (b
y b -> Seq b -> Seq b
forall a. a -> Seq a -> Seq a
:<| Seq b
accSeq, b -> HashSet b -> HashSet b
forall a. (Eq a, Hashable a) => a -> HashSet a -> HashSet a
HSet.insert b
y HashSet b
accSet)
      | Bool
otherwise = (Seq b
accSeq, HashSet b
accSet)
      where
        y :: b
y = a -> b
f a
x

fromSet :: HashSet a -> UniqueSeq a
fromSet :: forall a. HashSet a -> UniqueSeq a
fromSet HashSet a
set = Seq a -> HashSet a -> UniqueSeq a
forall a. Seq a -> HashSet a -> UniqueSeq a
UnsafeUniqueSeq Seq a
seq HashSet a
set
  where
    seq :: Seq a
seq = (a -> Seq a -> Seq a) -> Seq a -> HashSet a -> Seq a
forall a b. (a -> b -> b) -> b -> HashSet a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((Seq a -> a -> Seq a) -> a -> Seq a -> Seq a
forall a b c. (a -> b -> c) -> b -> a -> c
flip Seq a -> a -> Seq a
forall a. Seq a -> a -> Seq a
(:|>)) Seq a
forall a. Seq a
Seq.empty HashSet a
set

displayShow :: (Show a) => UniqueSeq a -> Text
displayShow :: forall a. Show a => UniqueSeq a -> Text
displayShow = (a -> Text) -> UniqueSeq a -> Text
forall a. (a -> Text) -> UniqueSeq a -> Text
display (String -> Text
T.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show)

display :: (a -> Text) -> UniqueSeq a -> Text
display :: forall a. (a -> Text) -> UniqueSeq a -> Text
display a -> Text
toText =
  Text -> [Text] -> Text
T.intercalate Text
","
    ([Text] -> Text) -> (UniqueSeq a -> [Text]) -> UniqueSeq a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Text) -> [a] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Text
toText
    ([a] -> [Text]) -> (UniqueSeq a -> [a]) -> UniqueSeq a -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seq a -> [a]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList
    (Seq a -> [a]) -> (UniqueSeq a -> Seq a) -> UniqueSeq a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' A_Getter NoIx (UniqueSeq a) (Seq a) -> UniqueSeq a -> Seq a
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Getter NoIx (UniqueSeq a) (Seq a)
#seq

-- | Operator alias for 'union'. U+222A.
--
-- @since 0.1
(∪) :: (Hashable a) => UniqueSeq a -> UniqueSeq a -> UniqueSeq a
∪ :: forall a. Hashable a => UniqueSeq a -> UniqueSeq a -> UniqueSeq a
(∪) = UniqueSeq a -> UniqueSeq a -> UniqueSeq a
forall a. Hashable a => UniqueSeq a -> UniqueSeq a -> UniqueSeq a
Internal.union

infixl 6 

-- | Fold over 'union'. U+22C3.
--
-- @since 0.1
(⋃) :: (Foldable f, Hashable a) => f (UniqueSeq a) -> UniqueSeq a
⋃ :: forall (f :: * -> *) a.
(Foldable f, Hashable a) =>
f (UniqueSeq a) -> UniqueSeq a
(⋃) = (UniqueSeq a -> UniqueSeq a -> UniqueSeq a)
-> UniqueSeq a -> f (UniqueSeq a) -> UniqueSeq a
forall b a. (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' UniqueSeq a -> UniqueSeq a -> UniqueSeq a
forall a. Hashable a => UniqueSeq a -> UniqueSeq a -> UniqueSeq a
(∪) UniqueSeq a
forall a. UniqueSeq a
empty

-- | Operator alias for 'member'. U+2216.
--
-- @since 0.1
(∈) :: (Hashable a) => a -> UniqueSeq a -> Bool
∈ :: forall a. Hashable a => a -> UniqueSeq a -> Bool
(∈) = a -> UniqueSeq a -> Bool
forall a. Hashable a => a -> UniqueSeq a -> Bool
member

infix 4 

-- | Negation of '(∈)'. U+2209.
--
-- @since 0.1
(∉) :: (Hashable a) => a -> UniqueSeq a -> Bool
∉ :: forall a. Hashable a => a -> UniqueSeq a -> Bool
(∉) a
x = Bool -> Bool
not (Bool -> Bool) -> (UniqueSeq a -> Bool) -> UniqueSeq a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> UniqueSeq a -> Bool
forall a. Hashable a => a -> UniqueSeq a -> Bool
(∈) a
x

infix 4 

-- | Flipped '(↤)'. U+21A6.
--
-- @since 0.1
(↦) :: (Hashable b) => UniqueSeq a -> (a -> b) -> UniqueSeq b
↦ :: forall b a. Hashable b => UniqueSeq a -> (a -> b) -> UniqueSeq b
(↦) = ((a -> b) -> UniqueSeq a -> UniqueSeq b)
-> UniqueSeq a -> (a -> b) -> UniqueSeq b
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> b) -> UniqueSeq a -> UniqueSeq b
forall b a. Hashable b => (a -> b) -> UniqueSeq a -> UniqueSeq b
(↤)

infix 3 

-- | Operator alias for 'map'. U+21A4.
--
-- @since 0.1
(↤) :: (Hashable b) => (a -> b) -> UniqueSeq a -> UniqueSeq b
↤ :: forall b a. Hashable b => (a -> b) -> UniqueSeq a -> UniqueSeq b
(↤) = (a -> b) -> UniqueSeq a -> UniqueSeq b
forall b a. Hashable b => (a -> b) -> UniqueSeq a -> UniqueSeq b
map

infix 3