module SegmentList
(segmentSizei,segmentSizeI,segmentList,segmentIndex)
where
import Data.List
import Data.Array
segmentSizei :: Int
segmentSizei = 100
segmentSizeI :: Integer
segmentSizeI = toInteger segmentSizei
-- |
-- Constructs a list in which chunks of sequential elements are held together
-- in an array, to improve access time. This is only intended for
-- use in an infinite list (otherwise just pack the entire thing
-- in one array).
--
segmentList :: [a] -> [Array Int a]
segmentList xs = let (firstGroup,restGroups) = seqSplitAt segmentSizei xs
in (listArray (0,segmentSizei-1) firstGroup) :
(segmentList restGroups)
seqSplitAt :: Int -> [a] -> ([a],[a])
seqSplitAt 0 xs = ([],xs)
seqSplitAt i (x:xs) = let rest = (seqSplitAt (i-1) xs)
in seq x $ (x : (fst rest),snd rest)
seqSplitAt i [] = error ("Tried to access " ++ (show i) ++ "'th element of []")
-- |
-- Retrieve an element from a segment list by index.
--
segmentIndex :: [Array Int a] -> Integer -> a
segmentIndex xss i = (xss `genericIndex` (i `div` segmentSizeI)) ! ((fromInteger i) `mod` segmentSizei)