TL;DR: linear-base seems to not provide me with a way to turn functions of type Handle -> IO a into Handle %1 -> RIO (Ur? a, Handle), and this seems to stop me from doing anything with ByteString.
I am trying to build a library to parse (and later, write) a data archive format from an old game, and do it with linear types to stretch myself. The file begins with a header listing the contents of all files in the archive, and their byte offsets into the archive itself. I want to write a function to return a ByteString stream from a Handle, when given the Record describing the name/offset/etc.
If I was using standard Haskell, I would write something like this, and trust the user not to abuse the Handle while streaming (we must hSeek to the offset and then stream the required number of bytes:
hGetRecord :: MonadIO m => Record -> Handle -> ByteStream m ()
But in linear-base, we seem to hit the following:
- We can't use the standard
streaming types, we have to use the one in Streaming.Linear.
- This means we can't use the
streaming-bytestring ByteStream type, and must use Stream (Of ByteString) from linear-base. Annoying, but OK.
The function I think I want to write with linear types:
hGetRecord :: Record -> Handle %1 -> Stream (Of ByteString) RIO Handle
This should let me safely seek the handle, without anyone interfering with it until the streaming is finished. But I cannot lift the ByteString I/O functions from System.IO.IO to RIO because the constructor for System.IO.Linear.Resource.Handle is not exported.
Describe the solution you'd like
I think that variants of unsafeFromSystemIOResource etc that allow me to bring Handle-using IO functions into RIO and have them play nicely with the existing Handle type in linear-base would give me everything I need, but that's probably an unsafe level of power. The functions I need are RIO versions of:
openBinaryFile
hSeek
Data.ByteString.Lazy.hGet
TL;DR:
linear-baseseems to not provide me with a way to turn functions of typeHandle -> IO aintoHandle %1 -> RIO (Ur? a, Handle), and this seems to stop me from doing anything withByteString.I am trying to build a library to parse (and later, write) a data archive format from an old game, and do it with linear types to stretch myself. The file begins with a header listing the contents of all files in the archive, and their byte offsets into the archive itself. I want to write a function to return a
ByteStringstream from aHandle, when given theRecorddescribing the name/offset/etc.If I was using standard Haskell, I would write something like this, and trust the user not to abuse the
Handlewhile streaming (we musthSeekto the offset and then stream the required number of bytes:But in
linear-base, we seem to hit the following:streamingtypes, we have to use the one inStreaming.Linear.streaming-bytestringByteStreamtype, and must useStream (Of ByteString)fromlinear-base. Annoying, but OK.The function I think I want to write with linear types:
This should let me safely seek the handle, without anyone interfering with it until the streaming is finished. But I cannot lift the
ByteStringI/O functions fromSystem.IO.IOtoRIObecause the constructor forSystem.IO.Linear.Resource.Handleis not exported.Describe the solution you'd like
I think that variants of
unsafeFromSystemIOResourceetc that allow me to bringHandle-usingIOfunctions intoRIOand have them play nicely with the existingHandletype inlinear-basewould give me everything I need, but that's probably an unsafe level of power. The functions I need areRIOversions of:openBinaryFilehSeekData.ByteString.Lazy.hGet