Lazy version of peekArray

Gracjan Polak gracjan at acchsh.com
Tue Jun 22 15:13:54 EDT 2004


Hi,

I'm trying to make use of memory mapped files with Haskell. It is kind 
of fun, I managed to mmap a file (actualy CreateFileMapping, because I'm 
on a Windows box), managed to setup finalizers (those kind of work now, 
see my posts about finalizers and FFI).

Now I got to content... and here is the problem.

Data I want to read is large, mostly binary with parts that must be 
parsed. But peekArray is not lazy (is IO action), produces large lists 
in strict mode. So I had to write my own thing. Provided that underlying 
data does not change following unsafeLazyPeekArray and friends should be 
good.

Does anybody see any problems in following code? Maybe there is 
something obvious I do not see...

Those functions were designed to be list less, when used in producer 
consumer fashion list will not be generated (I hope). Is current state 
GHC compiler smart enough to optimize this efficiently? How can I help 
it with this task (maybe a pragma here and there?)

Anyway, the code. Maybe someone find it interesting:



unsafeLazyPeekArray size ptr = unsafeLazyPeekArrayOffset 0 size ptr

unsafeLazyPeekArrayOffset :: Storable a =>
                      Int -> Int -> ForeignPtr a -> [a]
unsafeLazyPeekArrayOffset offset size ptr
     | size <= 0 = []
     | otherwise = unsafePerformIO $ helper offset
       where
           helper index | index >= size = return []
                        | otherwise = unsafeInterleaveIO $ do
                              x <- withForeignPtr ptr (\xptr ->
                                          peekElemOff xptr index)
                              xs <- helper (index+1)
                              return (x:xs)


unsafeLazyPeekArrayOffset0 :: (Storable a, Eq a) =>
             Int -> a -> ForeignPtr a -> [a]
unsafeLazyPeekArrayOffset0 offset marker ptr =
     unsafePerformIO $ helper offset
     where
         helper index = unsafeInterleaveIO $ do
                              x <- withForeignPtr ptr (\xptr ->
                                          peekElemOff xptr index)
                              if x==marker
                                  then return []
                                  else do
                                      xs <- helper (index+1)
                                      return (x:xs)



unsafeLazyPeekArray0 :: (Storable a, Eq a) => a -> ForeignPtr a -> [a]
unsafeLazyPeekArray0 marker ptr =
         unsafeLazyPeekArrayOffset0 0 marker ptr




-- 
Pozdrawiam, Regards,
Gracjan



More information about the Glasgow-haskell-users mailing list