module Stack (module Stack, module X) where
import Data.Maybe (fromJust)
import Data.Foldable as X (toList)
import Data.Set.Ordered (OSet, (|<))
import qualified Data.Set.Ordered as OS

type Stack a = OSet a

empty :: Stack a
empty :: Stack a
empty = Stack a
forall a. OSet a
OS.empty

singleton :: a -> Stack a
singleton :: a -> Stack a
singleton = a -> Stack a
forall a. a -> OSet a
OS.singleton

insert :: Ord a => a -> Stack a -> Stack a
insert :: a -> Stack a -> Stack a
insert = a -> Stack a -> Stack a
forall a. Ord a => a -> OSet a -> OSet a
(|<)

removeLast :: Ord a => Stack a -> Stack a
removeLast :: Stack a -> Stack a
removeLast Stack a
s = a -> Stack a -> Stack a
forall a. Ord a => a -> OSet a -> OSet a
OS.delete (Stack a -> a
forall a. Stack a -> a
Stack.last Stack a
s) Stack a
s

head :: Stack a -> a
head :: Stack a -> a
head = (Stack a -> Int -> a
forall a. Stack a -> Int -> a
`unsafeElemAt` Int
0)

safeHead :: Stack a -> Maybe a
safeHead :: Stack a -> Maybe a
safeHead = (Stack a -> Int -> Maybe a
forall a. Stack a -> Int -> Maybe a
`elemAt` Int
0)

last :: Stack a -> a
last :: Stack a -> a
last Stack a
s = Stack a
s Stack a -> Int -> a
forall a. Stack a -> Int -> a
`unsafeElemAt` (Stack a -> Int
forall a. Stack a -> Int
Stack.size Stack a
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)

pop :: Ord a => Stack a -> Stack a
pop :: Stack a -> Stack a
pop Stack a
s = a -> Stack a -> Stack a
forall a. Ord a => a -> OSet a -> OSet a
OS.delete (Stack a -> a
forall a. Stack a -> a
Stack.head Stack a
s) Stack a
s

popWithInfo :: Ord a => Stack a -> (Stack a, a, a)
popWithInfo :: Stack a -> (Stack a, a, a)
popWithInfo Stack a
s = let
  top :: a
top  = Stack a -> a
forall a. Stack a -> a
Stack.head Stack a
s
  s' :: Stack a
s'   = a -> Stack a -> Stack a
forall a. Ord a => a -> OSet a -> OSet a
OS.delete a
top Stack a
s
  top' :: a
top' = Stack a -> a
forall a. Stack a -> a
Stack.head Stack a
s' in
    (Stack a
s', a
top, a
top')

tail :: Ord a => Stack a -> [a]
tail :: Stack a -> [a]
tail = Stack a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Stack a -> [a]) -> (Stack a -> Stack a) -> Stack a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stack a -> Stack a
forall a. Ord a => Stack a -> Stack a
pop

elemAt :: Stack a -> Int -> Maybe a
elemAt :: Stack a -> Int -> Maybe a
elemAt = Stack a -> Int -> Maybe a
forall a. Stack a -> Int -> Maybe a
OS.elemAt

takeStack :: Ord a => Int -> Stack a -> Stack a
takeStack :: Int -> Stack a -> Stack a
takeStack Int
n = [a] -> Stack a
forall a. Ord a => [a] -> Stack a
fromList ([a] -> Stack a) -> (Stack a -> [a]) -> Stack a -> Stack a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
n ([a] -> [a]) -> (Stack a -> [a]) -> Stack a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stack a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList

unsafeElemAt :: Stack a -> Int -> a
unsafeElemAt :: Stack a -> Int -> a
unsafeElemAt Stack a
s = Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe a -> a) -> (Int -> Maybe a) -> Int -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stack a -> Int -> Maybe a
forall a. Stack a -> Int -> Maybe a
OS.elemAt Stack a
s

fromList :: Ord a => [a] -> Stack a
fromList :: [a] -> Stack a
fromList = [a] -> Stack a
forall a. Ord a => [a] -> Stack a
OS.fromList

-- toList :: Ord a => Stack a -> [a]
-- toList = toList

size :: Stack a -> Int
size :: Stack a -> Int
size = Stack a -> Int
forall a. Stack a -> Int
OS.size