The problem with your "bytesFromPointer" is that you take the packaged view, StorableArray from pngload, and want to convert it to another packed view, ByteString, passing through an intermediate list. Sometimes laziness means that an intermediate list will not be built in memory, but this is not so.
The mapM function is the first intruder. If you expand mapM (peekByteOff pointer) [0..(count-1)] , you will get
el0 <- peekByteOff pointer 0 el1 <- peekByteOff pointer 1 el2 <- peekByteOff pointer 2 ... eln <- peekByteOff pointer (count-1) return [el0,el1,el2,...eln]
since all these actions take place in the IO monad, they are performed in order. This means that each element of the output list must be constructed before the list is created, and laziness can never help you.
Even if the list was created lazily, as Don Stewart notes, the "pack" function will still ruin your work. The problem with the “package” is that it needs to know how many items in the list the correct amount of memory allocates. To find the length of the list, the program must go through it to the end. Due to the need to calculate the length, the list must be fully loaded before it can be packed into a byte string.
I consider "mapM" as well as "pack" as the smell of code. Sometimes you can replace mapM with "mapM_", but in this case it is better to use byte creation functions, for example. "PackCStringLen".
John l
source share