-- | The functions in this module perform no bounds checking. module Util.Internal.Array ( Array , empty , singleton , snoc , index , head, last , adjust , take , fromList2 , fromTail , toTail ) where import qualified Data.List.NonEmpty as L import Prelude hiding (head, last, take) import Data.Primitive.SmallArray type Array a = SmallArray a empty :: Array a empty = mempty singleton :: a -> Array a singleton x = runSmallArray $ newSmallArray 1 x snoc :: Array a -> a -> Array a snoc arr x = runSmallArray $ do let size = length arr arr' <- newSmallArray (size + 1) x copySmallArray arr' 0 arr 0 size pure arr' index :: Int -> Array a -> a index = flip indexSmallArray head :: Array a -> a head arr = indexSmallArray arr 0 last :: Array a -> a last arr = indexSmallArray arr (length arr - 1) -- | Update the element at the specified index. adjust :: Int -> (a -> a) -> Array a -> Array a adjust i f arr = runSmallArray $ do arr' <- thawSmallArray arr 0 (length arr) let x = indexSmallArray arr i writeSmallArray arr' i (f x) pure arr' {-# INLINE adjust #-} take :: Int -> Array a -> Array a take n arr = cloneSmallArray arr 0 n fromList2 :: a -> a -> Array a fromList2 x y = runSmallArray $ do arr <- newSmallArray 2 x writeSmallArray arr 1 y pure arr -- | Convert a full tail into an array. -- -- > fromTail = A.fromListN tailSize . reverse . toList fromTail :: Int -> L.NonEmpty a -> Array a fromTail size (x L.:| xs) = runSmallArray $ do arr <- newSmallArray size x let loop _ [] = pure () loop i (y : ys) = writeSmallArray arr i y *> loop (i - 1) ys loop (size - 2) xs pure arr -- | Convert an array into a tail. -- -- > toTail = L.fromList . reverse . toList toTail :: Array a -> L.NonEmpty a toTail = L.fromList . foldl (flip (:)) []