Not the solution to your problem, but a hint to the cause:
Haskell seems to be very conservative in memory reuse and when the interpreter sees the potential to reclaim a memory block, it goes for it. Your problem description fits the minor GC behavior described here (bottom)
https://wiki.haskell.org/GHC/Memory_Management.
New data are allocated in 512kb “nursery”. Once it’s exhausted, “minor
GC” occurs – it scans the nursery and frees unused values.
So if you chop the data into smaller chunks, you enable the engine to do the cleanup earlier – GC kicks in.