Using Netwire to spawn lists from a value

180 views Asked by At

I think I'm fundamentally misunderstanding how to attack this type of problem with Netwire:

I have the following test-case:

I'd like to take a string, split it into lines, print each line, then exit.

The pieces I'm missing are:

  • How to inhibit after a value early in a pipeline, but then if that value is split and the results produced later, not inhibit until all those results are consumed.
  • What the main loop function should look like
  • If I should use 'once'

Here is the code I have so far:

import Control.Wire

main :: IO ()
main = recur mainWire

recur :: Wire () IO () () -> IO ()
recur a = do
  (e,w) <- stepWire a 0 ()
  case e of Left  () -> return ()
            Right () -> recur w

mainWire :: Wire () IO () ()
mainWire = pure "asdf\nqwer\nzxcv"
       >>> once
       >>> arr lines
       >>> fifo
       >>> arr print
       >>> perform

This outputs the following:

"asdf"

and then quits. If I remove the once, then the program performs as expected, repeatedly outputting the full list of lines forever.

I'd like the following output:

"asdf"
"qwer"
"zxcv"

I'm sure that I'm just missing some intuition here about the correct way to approach this class of problem with Netwire.

1

There are 1 answers

1
Cubic On BEST ANSWER

Note: This is for an older version of netwire (before events worked like they do now), so some translating of the code would be required to make this work properly with the current version.


If I understood you right, you want a wire that produces the lines of a string, and then inhibits when it's done with that? It's a bit hard to tell.

once as the name implies, produces exactly once and then inhibits forever. Again it's a bit unclear what your wires are doing (because you didn't tell us) but it's not something you normally put into your "main" wire (so far I've only ever used once with andThen).

If that is correct, I'd probably do it something along the lines of:

produceLines s = produceLines' $ lines s where
  produceLines' [] = inhibit mempty
  produceLines' (l:ls) = pure s . once --> produceLines' ls

(You could write that as a fold or something, I just thought this was a bit clearer).

--> is pretty for andThen in case you didn't know. Basically this splits the passed string into lines, and turns them into a wire that produces the first line once, and then behaves like a similar wire except with the first element removed. It inhibits indefinitely once all values were produced.

Is that what you wanted?

Update

I see what you were trying to do now.

The wire you were trying to write could be done as

perform . arr print . fifo . ((arr lines . pure "asdf\nqwer\nzxcv" . once) --> pure [])

The part in the parentheses produce ["adf","nqwer","nzxc"] for one instant, and then produces [] forever. fifo takes values from the previous wire, adding the result from the previous wire in every instance (because of that we have to keep producing []). The rest is as you know it (I'm using the function-like notation rather than the arrow notation because I prefer it, but that shouldn't be a problem for you).