If the timeout is zero do a non-blocking check for matching messages. A
non-zero timeout is applied only when waiting for incoming messages (that is,
after we have checked the messages that are already in the mailbox).

This is synchronous in the sense that once it returns you are guaranteed
that no exception will be raised if the remote process dies. However, it is
asynchronous in the sense that we do not wait for a response from the remote
node.

Logging

say message sends a message (time, pid of the current process, message)
to the process registered as logger. By default, this process simply
sends the string to stderr. Individual Cloud Haskell backends might
replace this with a different logger process, however.

There is currently no synchronous version of whereisRemoteAsync: if
you implement one yourself, be sure to take into account that the remote
node might die or get disconnect before it can respond (i.e. you should
use monitorNode and take appropriate action when you receive a
NodeMonitorNotification).

Reconnecting

Cloud Haskell provides the illusion of connection-less, reliable, ordered
message passing. However, when network connections get disrupted this
illusion cannot always be maintained. Once a network connection breaks (even
temporarily) no further communication on that connection will be possible.
For example, if process A sends a message to process B, and A is then
notified (by monitor notification) that it got disconnected from B, A will
not be able to send any further messages to B, unless A explicitly
indicates that it is acceptable to attempt to reconnect to B using the
Cloud Haskell reconnect primitive.

Importantly, when A calls reconnect it acknowledges that some messages to
B might have been lost. For instance, if A sends messages m1 and m2 to B,
then receives a monitor notification that its connection to B has been lost,
calls reconnect and then sends m3, it is possible that B will receive m1
and m3 but not m2.

Note that reconnect does not mean reconnect now but rather /it is okay
to attempt to reconnect on the next send/. In particular, if no further
communication attempts are made to B then A can use reconnect to clean up
its connection to B.