[Haskell-cafe] Wrapping external process communication in a nice API?

Tristan Cacqueray tdecacqu at redhat.com
Mon May 31 15:56:03 UTC 2021

On Mon, May 31, 2021 at 17:31 Mario Lang wrote:
> Tristan Cacqueray <tdecacqu at redhat.com> writes:
>> On Sat, May 29, 2021 at 16:59 Mario Lang wrote:
>>> Hi.
>>> For my chessIO package, I wrote a module to communicate with
>>> UCI (Universal Chess Interface) speaking chess engines.
>>> This sort of thing is pretty new to me.
>>> I settled to use attoparsec for parsing and
>>> TChan to feed incoming data to the library users.
>>> This is the first thing that I found which looked like it could work...
>>> I would be thrilled if someone with more experience in this area would
>>> give my approach a review.  Let me know if something is glaringly
>>> unidiomatic, I am sure you will find things.
>>> https://github.com/mlang/chessIO/blob/master/src/Game/Chess/UCI.hs
>> It seems like it would be safer to use withCreateProcess instead of
>> createProcess to ensure the process is not left unattended.
> Maybe I am unimaginative, but it seems to me I can not use
> withCreateProcess as I need to read/write the Handles outside of the
> initialisation phase.  It seems to me withCreateProcess would kill my
> external process once my initialisation function is done.
> Or do I misunderstand bracket somehow?
> AIUI, withCreateProcess always calls cleanupProcess once the action is
> done, right?

I guess you would have to replace `start'` with something like:

withEngine :: Time unit -> ... -> (Engine -> IO ()) -> IO ()

And let your user provide the `Engine -> IO ()` callback.

Alternatively, perhaps the `managed` library can be used to get
something closer to your existing `start'`, e.g.:

>>> This is for me to learn, and to avoid putting weird stuff on hackage...
>>> I actually prefer private mail, but a GitHub issue or even a PR are also
>>> highly welcome.
>> I had the same need for a matrix bot where the events come from a ssh
>> process stream. There is `streaming-commons` and `conduit-extra`, but I
>> am not familiar enough with conduit to make it work.
>> In the end I used `turtle` to callback with each line output.
>> For what it worths, here is my current implementation:
>> https://github.com/softwarefactory-project/gerritbot-matrix/blob/71644a21a9ac942bb5b2819208cc0b949e02b084/src/Gerritbot.hs#L24
> Thanks.  The output of my subprocess is also line-based, so I use
> ByteString.hGetLine and a call into attoparsec to make sense of the
> output I receive.  Works so far.

You're welcome. Perhaps such line-based process wrapper could be a
useful addition to the hackage registry?

Note that I also tried to convert the Turtle.inproc Shell to a `pipes`
or `streaming`, but without success.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 515 bytes
Desc: not available
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20210531/6fa0b5d8/attachment.sig>

More information about the Haskell-Cafe mailing list