Here's my solution for the distributed chat server that allows nodes to join/leave at will:
https://gist.github.com/lylek/f30f6bd4d7a6898511cfa60e30fe71c4
Some lessons I learned:
I was getting some double MsgServerInfo messages. When a new server joins, after getting a WhereIsReply for each peer, it sends a MsgServerInfo to that peer. Then the peer sends back a MsgServerInfo. But then the first server was sending back yet another MsgServerInfo! That third one was getting ignored, because the remote server already knew the sender. But it still seemed like a waste of resources.
I thought at first perhaps I needed to keep track of which servers I had sent MsgServerInfos to. That seemed a bit complex. Then I realized that the message itself could be an indicator of whether it was the original message, or the reply. At first I thought I could have a MsgServerJoin for the original message, and a MsgServerInfo for the reply. But then I realized that I could just use a single data structure but put a flag in it.
When I later looked at the author's solution, it turned out he had done the exact same thing.
When you monitor the remote process, you're in some code that runs in STM. At first, to solve this problem, I tried to push the "monitor" command onto the proxy channel. Well, the "monitor" command ran, but then I was getting no notifications.
At first I thought perhaps the library was broken, and I was looking through the code. I thought maybe it didn't work on the Mac, or when the processes were on separate nodes. Then I remembered that the author's repo had a sample solution. I compiled and ran it. It worked fine. So, not a library problem!
I looked for differences between the author's solution and mine. I saw that he was doing a join right there in the handler for the MsgServerInfo message, in order to execute the command in the Process monad. I thought, but why can't I just as well push it into the proxy channel? I looked at the code handling the proxy channel, and realized that it was spawned as a separate process. So that process was getting the notifications! You can push all sorts of commands off onto the proxy channel, but 'monitor' is not one of them.
So, I followed the author's pattern and did a 'join' right there in the message handler.