As you discovered you can’t.
A long time ago a proposal was made to make Java-like composable IO classes but somehow it never caught in the larger eco-system (the fact that it used objects certainly has something to do with that).
More recently your problem would likely be solved by this “modular” IO RFC.
Personally I’m not super fond of it. With effects at the corner I would prefer that the Stdlib simply provides a more general notion of bytes IO that revolves around functions.
Something like:
type buffer = { bytes : bytes; start : int; len : int }
type input = unit -> buffer option
type output = buffer option -> unit
With None
consistently meaning end of input. The sub bytes specified by buffer
values returned by input
are owned by the receiver until the next call to input
. The sub bytes specified by buffer
given to output
are owned by output
until it returns.