When I needed to work with a lot of this kind of “withPtr” FFI, I made a newtype for it.
NestedIO is for IO stuff that needs to operate in these nested “with” contexts.
This newtype allows me to implement a wrapper for any of the “withPtr”-style functions with nest1 :: (forall r. (a -> IO r) -> IO r) -> NestedIO a
With this I can take withText :: Text -> NestedIO FgnStringLen
and then use traverse
to do a version of what you’re asking about:
traverse withText :: [Text] -> NestedIO [FgnStringLen]
Then you can see this in a larger example like in withRawIrcMsg where a great many “withPtr” like operations are all chained together.