module PrimitiveExtras.SmallArray
where

import PrimitiveExtras.Prelude
import PrimitiveExtras.Types
import GHC.Exts hiding (toList)
import qualified Focus
import qualified ListT


{-| A workaround for the weird forcing of 'undefined' values int 'newSmallArray' -}
{-# INLINE newEmptySmallArray #-}
newEmptySmallArray :: PrimMonad m => Int -> m (SmallMutableArray (PrimState m) a)
newEmptySmallArray :: Int -> m (SmallMutableArray (PrimState m) a)
newEmptySmallArray Int
size = Int -> a -> m (SmallMutableArray (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (SmallMutableArray (PrimState m) a)
newSmallArray Int
size (Integer -> a
forall a b. a -> b
unsafeCoerce Integer
0)

{-# INLINE list #-}
list :: [a] -> SmallArray a
list :: [a] -> SmallArray a
list [a]
list =
  let
    !size :: Int
size = [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
list
    in (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
forall a. (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
runSmallArray ((forall s. ST s (SmallMutableArray s a)) -> SmallArray a)
-> (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
forall a b. (a -> b) -> a -> b
$ do
      SmallMutableArray s a
m <- Int -> ST s (SmallMutableArray (PrimState (ST s)) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> m (SmallMutableArray (PrimState m) a)
newEmptySmallArray Int
size
      let populate :: Int -> [a] -> ST s (SmallMutableArray s a)
populate Int
index [a]
list = case [a]
list of
            a
element : [a]
list -> do
              SmallMutableArray (PrimState (ST s)) a -> Int -> a -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a -> Int -> a -> m ()
writeSmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
m Int
index a
element
              Int -> [a] -> ST s (SmallMutableArray s a)
populate (Int -> Int
forall a. Enum a => a -> a
succ Int
index) [a]
list
            [] -> SmallMutableArray s a -> ST s (SmallMutableArray s a)
forall (m :: * -> *) a. Monad m => a -> m a
return SmallMutableArray s a
m
          in Int -> [a] -> ST s (SmallMutableArray s a)
populate Int
0 [a]
list

-- |
-- Remove an element.
{-# INLINE unset #-}
unset :: Int -> SmallArray a -> SmallArray a
unset :: Int -> SmallArray a -> SmallArray a
unset Int
index SmallArray a
array =
  {-# SCC "unset" #-}
  let !size :: Int
size = SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array
      !newSize :: Int
newSize = Int -> Int
forall a. Enum a => a -> a
pred Int
size
      !newIndex :: Int
newIndex = Int -> Int
forall a. Enum a => a -> a
succ Int
index
      !amountOfFollowingElements :: Int
amountOfFollowingElements = Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
newIndex
      in (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
forall a. (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
runSmallArray ((forall s. ST s (SmallMutableArray s a)) -> SmallArray a)
-> (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
forall a b. (a -> b) -> a -> b
$ do
        SmallMutableArray s a
newMa <- Int -> a -> ST s (SmallMutableArray (PrimState (ST s)) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (SmallMutableArray (PrimState m) a)
newSmallArray Int
newSize a
forall a. HasCallStack => a
undefined
        SmallMutableArray (PrimState (ST s)) a
-> Int -> SmallArray a -> Int -> Int -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a
-> Int -> SmallArray a -> Int -> Int -> m ()
copySmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
newMa Int
0 SmallArray a
array Int
0 Int
index
        SmallMutableArray (PrimState (ST s)) a
-> Int -> SmallArray a -> Int -> Int -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a
-> Int -> SmallArray a -> Int -> Int -> m ()
copySmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
newMa Int
index SmallArray a
array Int
newIndex Int
amountOfFollowingElements
        SmallMutableArray s a -> ST s (SmallMutableArray s a)
forall (m :: * -> *) a. Monad m => a -> m a
return SmallMutableArray s a
newMa

{-# INLINE set #-}
set :: Int -> a -> SmallArray a -> SmallArray a
set :: Int -> a -> SmallArray a -> SmallArray a
set Int
index a
a SmallArray a
array =
  {-# SCC "set" #-} 
  let
    size :: Int
size = SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array
    in (forall s. ST s (SmallArray a)) -> SmallArray a
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (SmallArray a)) -> SmallArray a)
-> (forall s. ST s (SmallArray a)) -> SmallArray a
forall a b. (a -> b) -> a -> b
$ do
      SmallMutableArray s a
m <- SmallArray a
-> Int -> Int -> ST s (SmallMutableArray (PrimState (ST s)) a)
forall (m :: * -> *) a.
PrimMonad m =>
SmallArray a -> Int -> Int -> m (SmallMutableArray (PrimState m) a)
thawSmallArray SmallArray a
array Int
0 Int
size
      SmallMutableArray (PrimState (ST s)) a -> Int -> a -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a -> Int -> a -> m ()
writeSmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
m Int
index a
a
      SmallMutableArray (PrimState (ST s)) a -> ST s (SmallArray a)
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a -> m (SmallArray a)
unsafeFreezeSmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
m

{-# INLINE insert #-}
insert :: Int -> a -> SmallArray a -> SmallArray a
insert :: Int -> a -> SmallArray a -> SmallArray a
insert Int
index a
a SmallArray a
array =
  {-# SCC "insert" #-} 
  let
    !size :: Int
size = SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array
    !newSize :: Int
newSize = Int -> Int
forall a. Enum a => a -> a
succ Int
size
    !nextIndex :: Int
nextIndex = Int -> Int
forall a. Enum a => a -> a
succ Int
index
    !amountOfFollowingElements :: Int
amountOfFollowingElements = Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
index
    in (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
forall a. (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
runSmallArray ((forall s. ST s (SmallMutableArray s a)) -> SmallArray a)
-> (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
forall a b. (a -> b) -> a -> b
$ do
      SmallMutableArray s a
newMa <- Int -> a -> ST s (SmallMutableArray (PrimState (ST s)) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (SmallMutableArray (PrimState m) a)
newSmallArray Int
newSize a
a
      SmallMutableArray (PrimState (ST s)) a
-> Int -> SmallArray a -> Int -> Int -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a
-> Int -> SmallArray a -> Int -> Int -> m ()
copySmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
newMa Int
0 SmallArray a
array Int
0 Int
index
      SmallMutableArray (PrimState (ST s)) a
-> Int -> SmallArray a -> Int -> Int -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a
-> Int -> SmallArray a -> Int -> Int -> m ()
copySmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
newMa Int
nextIndex SmallArray a
array Int
index Int
amountOfFollowingElements
      SmallMutableArray s a -> ST s (SmallMutableArray s a)
forall (m :: * -> *) a. Monad m => a -> m a
return SmallMutableArray s a
newMa

{-# INLINE adjust #-}
adjust :: (a -> a) -> Int -> SmallArray a -> SmallArray a
adjust :: (a -> a) -> Int -> SmallArray a -> SmallArray a
adjust a -> a
fn Int
index SmallArray a
array =
  let
    size :: Int
size = SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array
    in if Int
size Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
index Bool -> Bool -> Bool
&& Int
index Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0
      then (a -> a) -> Int -> Int -> SmallArray a -> SmallArray a
forall a. (a -> a) -> Int -> Int -> SmallArray a -> SmallArray a
unsafeAdjustWithSize a -> a
fn Int
index Int
size SmallArray a
array
      else SmallArray a
array

{-# INLINE unsafeAdjust #-}
unsafeAdjust :: (a -> a) -> Int -> SmallArray a -> SmallArray a
unsafeAdjust :: (a -> a) -> Int -> SmallArray a -> SmallArray a
unsafeAdjust a -> a
fn Int
index SmallArray a
array =
  (a -> a) -> Int -> Int -> SmallArray a -> SmallArray a
forall a. (a -> a) -> Int -> Int -> SmallArray a -> SmallArray a
unsafeAdjustWithSize a -> a
fn Int
index (SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array) SmallArray a
array

{-# INLINE unsafeAdjustWithSize #-}
unsafeAdjustWithSize :: (a -> a) -> Int -> Int -> SmallArray a -> SmallArray a
unsafeAdjustWithSize :: (a -> a) -> Int -> Int -> SmallArray a -> SmallArray a
unsafeAdjustWithSize a -> a
fn Int
index Int
size SmallArray a
array =
  (forall s. ST s (SmallArray a)) -> SmallArray a
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (SmallArray a)) -> SmallArray a)
-> (forall s. ST s (SmallArray a)) -> SmallArray a
forall a b. (a -> b) -> a -> b
$ do
    SmallMutableArray s a
m <- SmallArray a
-> Int -> Int -> ST s (SmallMutableArray (PrimState (ST s)) a)
forall (m :: * -> *) a.
PrimMonad m =>
SmallArray a -> Int -> Int -> m (SmallMutableArray (PrimState m) a)
thawSmallArray SmallArray a
array Int
0 Int
size
    a
element <- SmallMutableArray (PrimState (ST s)) a -> Int -> ST s a
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a -> Int -> m a
readSmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
m Int
index
    SmallMutableArray (PrimState (ST s)) a -> Int -> a -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a -> Int -> a -> m ()
writeSmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
m Int
index (a -> ST s ()) -> a -> ST s ()
forall a b. (a -> b) -> a -> b
$! a -> a
fn a
element
    SmallMutableArray (PrimState (ST s)) a -> ST s (SmallArray a)
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a -> m (SmallArray a)
unsafeFreezeSmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
m

{-# INLINE cons #-}
cons :: a -> SmallArray a -> SmallArray a
cons :: a -> SmallArray a -> SmallArray a
cons a
a SmallArray a
array =
  {-# SCC "cons" #-} 
  let
    size :: Int
size = SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array
    newSize :: Int
newSize = Int -> Int
forall a. Enum a => a -> a
succ Int
size
    in (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
forall a. (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
runSmallArray ((forall s. ST s (SmallMutableArray s a)) -> SmallArray a)
-> (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
forall a b. (a -> b) -> a -> b
$ do
      SmallMutableArray s a
newMa <- Int -> a -> ST s (SmallMutableArray (PrimState (ST s)) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (SmallMutableArray (PrimState m) a)
newSmallArray Int
newSize a
a
      SmallMutableArray (PrimState (ST s)) a
-> Int -> SmallArray a -> Int -> Int -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a
-> Int -> SmallArray a -> Int -> Int -> m ()
copySmallArray SmallMutableArray s a
SmallMutableArray (PrimState (ST s)) a
newMa Int
1 SmallArray a
array Int
0 Int
size
      SmallMutableArray s a -> ST s (SmallMutableArray s a)
forall (m :: * -> *) a. Monad m => a -> m a
return SmallMutableArray s a
newMa

{-# INLINE orderedPair #-}
orderedPair :: Int -> e -> Int -> e -> SmallArray e
orderedPair :: Int -> e -> Int -> e -> SmallArray e
orderedPair Int
i1 e
e1 Int
i2 e
e2 =
  {-# SCC "orderedPair" #-} 
  (forall s. ST s (SmallMutableArray s e)) -> SmallArray e
forall a. (forall s. ST s (SmallMutableArray s a)) -> SmallArray a
runSmallArray ((forall s. ST s (SmallMutableArray s e)) -> SmallArray e)
-> (forall s. ST s (SmallMutableArray s e)) -> SmallArray e
forall a b. (a -> b) -> a -> b
$ if 
    | Int
i1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
i2 -> do
      SmallMutableArray s e
a <- Int -> e -> ST s (SmallMutableArray (PrimState (ST s)) e)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (SmallMutableArray (PrimState m) a)
newSmallArray Int
2 e
e1
      SmallMutableArray (PrimState (ST s)) e -> Int -> e -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a -> Int -> a -> m ()
writeSmallArray SmallMutableArray s e
SmallMutableArray (PrimState (ST s)) e
a Int
1 e
e2
      SmallMutableArray s e -> ST s (SmallMutableArray s e)
forall (m :: * -> *) a. Monad m => a -> m a
return SmallMutableArray s e
a
    | Int
i1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
i2 -> do
      SmallMutableArray s e
a <- Int -> e -> ST s (SmallMutableArray (PrimState (ST s)) e)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (SmallMutableArray (PrimState m) a)
newSmallArray Int
2 e
e1
      SmallMutableArray (PrimState (ST s)) e -> Int -> e -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
SmallMutableArray (PrimState m) a -> Int -> a -> m ()
writeSmallArray SmallMutableArray s e
SmallMutableArray (PrimState (ST s)) e
a Int
0 e
e2
      SmallMutableArray s e -> ST s (SmallMutableArray s e)
forall (m :: * -> *) a. Monad m => a -> m a
return SmallMutableArray s e
a
    | Bool
otherwise -> do
      SmallMutableArray s e
a <- Int -> e -> ST s (SmallMutableArray (PrimState (ST s)) e)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (SmallMutableArray (PrimState m) a)
newSmallArray Int
1 e
e2
      SmallMutableArray s e -> ST s (SmallMutableArray s e)
forall (m :: * -> *) a. Monad m => a -> m a
return SmallMutableArray s e
a

{-# INLINE findAndReplace #-}
findAndReplace :: (a -> Maybe a) -> SmallArray a -> SmallArray a
findAndReplace :: (a -> Maybe a) -> SmallArray a -> SmallArray a
findAndReplace a -> Maybe a
f SmallArray a
array =
  let
    size :: Int
size = SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array
    iterate :: Int -> SmallArray a
iterate Int
index =
      if Int
index Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
size
        then case a -> Maybe a
f (SmallArray a -> Int -> a
forall a. SmallArray a -> Int -> a
indexSmallArray SmallArray a
array Int
index) of
          Just a
newElement -> Int -> a -> SmallArray a -> SmallArray a
forall a. Int -> a -> SmallArray a -> SmallArray a
set Int
index a
newElement SmallArray a
array
          Maybe a
Nothing -> Int -> SmallArray a
iterate (Int -> Int
forall a. Enum a => a -> a
succ Int
index)
        else SmallArray a
array
    in Int -> SmallArray a
iterate Int
0

{-# INLINE findAndMap #-}
findAndMap :: (a -> Maybe b) -> SmallArray a -> Maybe b
findAndMap :: (a -> Maybe b) -> SmallArray a -> Maybe b
findAndMap a -> Maybe b
f SmallArray a
array =
  let
    size :: Int
size = SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array
    iterate :: Int -> Maybe b
iterate Int
index =
      if Int
index Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
size
        then case a -> Maybe b
f (SmallArray a -> Int -> a
forall a. SmallArray a -> Int -> a
indexSmallArray SmallArray a
array Int
index) of
          Just b
b -> b -> Maybe b
forall a. a -> Maybe a
Just b
b
          Maybe b
Nothing -> Int -> Maybe b
iterate (Int -> Int
forall a. Enum a => a -> a
succ Int
index)
        else Maybe b
forall a. Maybe a
Nothing
    in Int -> Maybe b
iterate Int
0

{-# INLINE find #-}
find :: (a -> Bool) -> SmallArray a -> Maybe a
find :: (a -> Bool) -> SmallArray a -> Maybe a
find a -> Bool
test SmallArray a
array =
  {-# SCC "find" #-} 
  let
    !size :: Int
size = SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array
    iterate :: Int -> Maybe a
iterate !Int
index = if Int
index Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
size
      then let
        !element :: a
element = SmallArray a -> Int -> a
forall a. SmallArray a -> Int -> a
indexSmallArray SmallArray a
array Int
index
        in if a -> Bool
test a
element
          then a -> Maybe a
forall a. a -> Maybe a
Just a
element
          else Int -> Maybe a
iterate (Int -> Int
forall a. Enum a => a -> a
succ Int
index)
      else Maybe a
forall a. Maybe a
Nothing
    in Int -> Maybe a
iterate Int
0

{-# INLINE findWithIndex #-}
findWithIndex :: (a -> Bool) -> SmallArray a -> Maybe (Int, a)
findWithIndex :: (a -> Bool) -> SmallArray a -> Maybe (Int, a)
findWithIndex a -> Bool
test SmallArray a
array =
  {-# SCC "findWithIndex" #-} 
  let
    !size :: Int
size = SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array
    iterate :: Int -> Maybe (Int, a)
iterate !Int
index = if Int
index Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
size
      then let
        !element :: a
element = SmallArray a -> Int -> a
forall a. SmallArray a -> Int -> a
indexSmallArray SmallArray a
array Int
index
        in if a -> Bool
test a
element
          then (Int, a) -> Maybe (Int, a)
forall a. a -> Maybe a
Just (Int
index, a
element)
          else Int -> Maybe (Int, a)
iterate (Int -> Int
forall a. Enum a => a -> a
succ Int
index)
      else Maybe (Int, a)
forall a. Maybe a
Nothing
    in Int -> Maybe (Int, a)
iterate Int
0

{-# INLINE elementsUnfoldlM #-}
elementsUnfoldlM :: Monad m => SmallArray e -> UnfoldlM m e
elementsUnfoldlM :: SmallArray e -> UnfoldlM m e
elementsUnfoldlM SmallArray e
array = (forall x. (x -> e -> m x) -> x -> m x) -> UnfoldlM m e
forall (m :: * -> *) a.
(forall x. (x -> a -> m x) -> x -> m x) -> UnfoldlM m a
UnfoldlM ((forall x. (x -> e -> m x) -> x -> m x) -> UnfoldlM m e)
-> (forall x. (x -> e -> m x) -> x -> m x) -> UnfoldlM m e
forall a b. (a -> b) -> a -> b
$ \ x -> e -> m x
step x
initialState -> let
  !size :: Int
size = SmallArray e -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray e
array
  iterate :: Int -> x -> m x
iterate Int
index !x
state = if Int
index Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
size
    then do
      e
element <- SmallArray e -> Int -> m e
forall (m :: * -> *) a. Monad m => SmallArray a -> Int -> m a
indexSmallArrayM SmallArray e
array Int
index
      x
newState <- x -> e -> m x
step x
state e
element
      Int -> x -> m x
iterate (Int -> Int
forall a. Enum a => a -> a
succ Int
index) x
newState
    else x -> m x
forall (m :: * -> *) a. Monad m => a -> m a
return x
state
  in Int -> x -> m x
iterate Int
0 x
initialState

{-# INLINE elementsListT #-}
elementsListT :: Monad m => SmallArray a -> ListT m a
elementsListT :: SmallArray a -> ListT m a
elementsListT = SmallArray a -> ListT m a
forall (m :: * -> *) (f :: * -> *) a.
(Monad m, Foldable f) =>
f a -> ListT m a
ListT.fromFoldable

{-# INLINE onFoundElementFocus #-}
onFoundElementFocus :: Monad m => (a -> Bool) -> (a -> Bool) -> Focus a m b -> Focus (SmallArray a) m b
onFoundElementFocus :: (a -> Bool)
-> (a -> Bool) -> Focus a m b -> Focus (SmallArray a) m b
onFoundElementFocus a -> Bool
testAsKey a -> Bool
testWholeEntry (Focus m (b, Change a)
concealA a -> m (b, Change a)
revealA) = m (b, Change (SmallArray a))
-> (SmallArray a -> m (b, Change (SmallArray a)))
-> Focus (SmallArray a) m b
forall element (m :: * -> *) result.
m (result, Change element)
-> (element -> m (result, Change element))
-> Focus element m result
Focus m (b, Change (SmallArray a))
concealArray SmallArray a -> m (b, Change (SmallArray a))
revealArray where
  concealArray :: m (b, Change (SmallArray a))
concealArray = ((b, Change a) -> (b, Change (SmallArray a)))
-> m (b, Change a) -> m (b, Change (SmallArray a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Change a -> Change (SmallArray a))
-> (b, Change a) -> (b, Change (SmallArray a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Change a -> Change (SmallArray a)
forall (f :: * -> *) a. Applicative f => Change a -> Change (f a)
arrayChange) m (b, Change a)
concealA where
    arrayChange :: Change a -> Change (f a)
arrayChange = \ case
      Focus.Set a
newEntry -> f a -> Change (f a)
forall a. a -> Change a
Focus.Set (a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
newEntry)
      Change a
_ -> Change (f a)
forall a. Change a
Focus.Leave
  revealArray :: SmallArray a -> m (b, Change (SmallArray a))
revealArray SmallArray a
array = case (a -> Bool) -> SmallArray a -> Maybe (Int, a)
forall a. (a -> Bool) -> SmallArray a -> Maybe (Int, a)
findWithIndex a -> Bool
testAsKey SmallArray a
array of
    Just (Int
index, a
entry) -> ((b, Change a) -> (b, Change (SmallArray a)))
-> m (b, Change a) -> m (b, Change (SmallArray a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Change a -> Change (SmallArray a))
-> (b, Change a) -> (b, Change (SmallArray a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Change a -> Change (SmallArray a)
arrayChange) (a -> m (b, Change a)
revealA a
entry) where
      arrayChange :: Change a -> Change (SmallArray a)
arrayChange = \ case
        Change a
Focus.Leave -> Change (SmallArray a)
forall a. Change a
Focus.Leave
        Focus.Set a
newEntry -> if a -> Bool
testWholeEntry a
newEntry
          then Change (SmallArray a)
forall a. Change a
Focus.Leave
          else SmallArray a -> Change (SmallArray a)
forall a. a -> Change a
Focus.Set (Int -> a -> SmallArray a -> SmallArray a
forall a. Int -> a -> SmallArray a -> SmallArray a
set Int
index a
newEntry SmallArray a
array)
        Change a
Focus.Remove -> if SmallArray a -> Int
forall a. SmallArray a -> Int
sizeofSmallArray SmallArray a
array Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
          then SmallArray a -> Change (SmallArray a)
forall a. a -> Change a
Focus.Set (Int -> SmallArray a -> SmallArray a
forall a. Int -> SmallArray a -> SmallArray a
unset Int
index SmallArray a
array)
          else Change (SmallArray a)
forall a. Change a
Focus.Remove
    Maybe (Int, a)
Nothing -> ((b, Change a) -> (b, Change (SmallArray a)))
-> m (b, Change a) -> m (b, Change (SmallArray a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Change a -> Change (SmallArray a))
-> (b, Change a) -> (b, Change (SmallArray a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Change a -> Change (SmallArray a)
arrayChange) m (b, Change a)
concealA where
      arrayChange :: Change a -> Change (SmallArray a)
arrayChange = \ case
        Focus.Set a
newEntry -> SmallArray a -> Change (SmallArray a)
forall a. a -> Change a
Focus.Set (a -> SmallArray a -> SmallArray a
forall a. a -> SmallArray a -> SmallArray a
cons a
newEntry SmallArray a
array)
        Change a
_ -> Change (SmallArray a)
forall a. Change a
Focus.Leave

{-# INLINE focusOnFoundElement #-}
focusOnFoundElement :: Monad m => Focus a m b -> (a -> Bool) -> (a -> Bool) -> SmallArray a -> m (b, SmallArray a)
focusOnFoundElement :: Focus a m b
-> (a -> Bool)
-> (a -> Bool)
-> SmallArray a
-> m (b, SmallArray a)
focusOnFoundElement Focus a m b
focus a -> Bool
testAsKey a -> Bool
testWholeEntry = case (a -> Bool)
-> (a -> Bool) -> Focus a m b -> Focus (SmallArray a) m b
forall (m :: * -> *) a b.
Monad m =>
(a -> Bool)
-> (a -> Bool) -> Focus a m b -> Focus (SmallArray a) m b
onFoundElementFocus a -> Bool
testAsKey a -> Bool
testWholeEntry Focus a m b
focus of
  Focus m (b, Change (SmallArray a))
conceal SmallArray a -> m (b, Change (SmallArray a))
reveal -> \ SmallArray a
sa -> do
    (b
b, Change (SmallArray a)
change) <- SmallArray a -> m (b, Change (SmallArray a))
reveal SmallArray a
sa
    (b, SmallArray a) -> m (b, SmallArray a)
forall (m :: * -> *) a. Monad m => a -> m a
return ((b, SmallArray a) -> m (b, SmallArray a))
-> (b, SmallArray a) -> m (b, SmallArray a)
forall a b. (a -> b) -> a -> b
$ (b
b,) (SmallArray a -> (b, SmallArray a))
-> SmallArray a -> (b, SmallArray a)
forall a b. (a -> b) -> a -> b
$ case Change (SmallArray a)
change of
      Change (SmallArray a)
Focus.Leave -> SmallArray a
sa
      Focus.Set SmallArray a
newSa -> SmallArray a
newSa
      Change (SmallArray a)
Focus.Remove -> SmallArray a
forall (f :: * -> *) a. Alternative f => f a
empty

toList :: forall a. SmallArray a -> [a]
toList :: SmallArray a -> [a]
toList SmallArray a
array = UnfoldlM Identity a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
PrimitiveExtras.Prelude.toList (SmallArray a -> UnfoldlM Identity a
forall (m :: * -> *) e. Monad m => SmallArray e -> UnfoldlM m e
elementsUnfoldlM SmallArray a
array :: UnfoldlM Identity a)