Netwire woes: creating a wire with mkGen_

Hello -cafe, a few days ago I posted this [1] in beginners, I'll pester you too before giving up. tl;dr: I want to create a wire which outputs a stream of 'q's when the letter Q is pressed and a stream of 'a' when the letter A is pressed. What I wrote is not working and I suspect I am not using mkGen_ correctly. Any pointers appreciated! [1] https://mail.haskell.org/pipermail/beginners/2016-December/017276.html

Hi,
tl;dr: I want to create a wire which outputs a stream of 'q's when the letter Q is pressed and a stream of 'a' when the letter A is pressed. What I wrote is not working and I suspect I am not using mkGen_ correctly.
could you show us the source code of your event wires? I suspect that this is not a Netwire issue at all, but an issue of one of the event wires draining the MVar, so the other one never actually sees a full MVar. Greets, ertes

On Fri, Dec 30, 2016 at 05:16:21PM +0100, Ertugrul Söylemez wrote:
could you show us the source code of your event wires? I suspect that this is not a Netwire issue at all, but an issue of one of the event wires draining the MVar, so the other one never actually sees a full MVar.
Hello Ertes, the source code is attached to the original message [1]; I'll paste here the relevant bits. This is the wire where the events are generated:
keyEvent :: Wire s () IO (MVar Char) (Event Char) keyEvent = mkGen_ f where f :: MVar Char -> IO (Either () (Event Char)) f r = tryTakeMVar r >>= \mmv -> case mmv of Nothing -> return $ Right NoEvent Just c -> putStrLn ("pop: " ++ [c]) >> return (Right (Event c))
And these are the three wires which filter/merge `keyEvent`(s):
keyA, keyQ :: Wire s () IO (MVar Char) (Event Char) keyQ = filterE (== 'q') . keyEvent keyA = filterE (== 'a') . keyEvent
testWire2 :: Wire s () IO (MVar Char) Char testWire2 = hold . (keyQ &> keyA)
`testWire2` is the function that is giving me headaches (works for Q keypresses but not A ones). [1] https://mail.haskell.org/pipermail/beginners/attachments/20161227/c0585a78/a...

keyQ = filterE (== 'q') . keyEvent keyA = filterE (== 'a') . keyEvent
testWire2 = hold . (keyQ &> keyA)
This is the problem. You actually have the 'keyEvent' wire twice in there, which means that both are trying to take from the 'MVar', which in turn means that in any frame if keyQ gets nothing, it's very unlikely that keyA will get something (because it runs pretty much directly after keyQ), and whenever keyQ gets something, it will clear the MVar, so keyA gets nothing again. The real solution is not to have keyEvent twice in there: proc _ -> do keys <- keyEvent -< () qKeys <- filterE (== 'q') -< keys aKeys <- filterE (== 'a') -< keys hold -< mergeL qKeys aKeys Perhaps you would like to try the new [wires] library, which has a much cleaner distinction between frameworks and the actual FRP description, so mistakes like this are far less likely. It's a cleaner library than Netwire in general. =) [wires]: https://hackage.haskell.org/package/wires Greets ertes

On Sat, Dec 31, 2016 at 01:50:28AM +0100, Ertugrul Söylemez wrote:
This is the problem. You actually have the 'keyEvent' wire twice in there, which means that both are trying to take from the 'MVar', which in turn means that in any frame if keyQ gets nothing, it's very unlikely that keyA will get something (because it runs pretty much directly after keyQ), and whenever keyQ gets something, it will clear the MVar, so keyA gets nothing again. The real solution is not to have keyEvent twice in there:
proc _ -> do keys <- keyEvent -< () qKeys <- filterE (== 'q') -< keys aKeys <- filterE (== 'a') -< keys hold -< mergeL qKeys aKeys
Very helpful, it's clear now (pity we have to use arrow interface, I much preferred applicative). I'll check `wires` too as suggested. Thanks again -F
participants (2)
-
Ertugrul Söylemez
-
Francesco Ariis