{-# LANGUAGE CPP #-} module Twee.Array where #include "errors.h" import qualified Data.Primitive as P import Control.Monad.ST import Data.List -- Zero-indexed dynamic arrays. -- Optimised for lookup. Modification is slow. data Array a = Array { arraySize :: {-# UNPACK #-} !Int, arrayContents :: {-# UNPACK #-} !(P.Array a) } class Default a where def :: a toList :: Array a -> [(Int, a)] toList arr = [ (i, x) | i <- [0..arraySize arr-1], let x = P.indexArray (arrayContents arr) i ] instance Show a => Show (Array a) where show arr = "{" ++ intercalate ", " [ show i ++ "->" ++ show x | (i, x) <- toList arr ] ++ "}" newArray :: Default a => Array a newArray = runST $ do marr <- P.newArray 0 def arr <- P.unsafeFreezeArray marr return (Array 0 arr) {-# INLINE (!) #-} (!) :: Default a => Array a -> Int -> a arr ! n | 0 <= n && n < arraySize arr = P.indexArray (arrayContents arr) n | otherwise = def {-# INLINEABLE update #-} update :: Default a => Int -> a -> Array a -> Array a update n x arr = runST $ do let size = arraySize arr `max` (n+1) marr <- P.newArray size def P.copyArray marr 0 (arrayContents arr) 0 (arraySize arr) P.writeArray marr n x arr' <- P.unsafeFreezeArray marr return (Array size arr')