
Heinrich Apfelmus
I concur that chaining wires with the andThen combinator is very slick, I like it a lot. Wolfgang Jeltsch recently described a similar pattern for classical FRP, namely a behavior that doesn't live forever, but actually ends at some point in time, which can be interpreted as an event occurrence. ("It ends with a bang!")
Well, that would work, but I wonder why then you wouldn't want to go all the way to signal inhibition. You don't need AFRP to have it. It's actually quite a light-weight change. Allow behaviors not to produce a value, i.e. somewhere in your library replace "a" by "Maybe a".
However, do note that the andThen combinator in netwire can only be so slick because "switching restarts time" (as the documentation puts it). I don't see a nice way to switch between wires that have accumulated state.
Time doesn't necessarily restart. This choice is left to the (-->) combinator. I've decided for that one to restart time, because it more closely resembles the behavior of other libraries. As a counterexample consider this: time . holdFor 0.5 (periodically 1) <|> 2*time This wire will switch back and forth between the two wires 'time' and '2*time' filling the gap between the inactive times of each. Unlike (-->), the (<|>) combinator keeps state. This is also true for the context wires (see below).
How would you express the TwoCounters example [1] using dynamic event switching in netwire? (The example can be implemented without dynamic event switching, but that's not what I mean.) What about the BarTab example [2]?
I've been asked that via private mail. Let me just quote my answer: "This is a misconception caused by the very different nature of Netwire. In Netwire everything is dynamic. What really happens in w1 --> w2 is that at the beginning only w1 exists. When it inhibits it is removed from the network and w2 takes its place. The missing ingredient is that w2 is not actually produced by a wire, but this is equally easy and natural. Just consider the context wires: context id w This wire will dynamically create a version of 'w' for every different input, so it acts like a router that will create wires if they don't already exist. Deletion works similarly: contextLatest id 1000 w This is a version that only keeps the 1000 latest contexts. There is also the classic dynamic switcher called 'switch': switch nw w This wire acts like 'w' until 'nw' produces a new wire, then switches to that one. Indeed 'nw' is of type Wire e m a (Wire e m a b). Really nothing is static in Netwire. It's actually very easy to write combinators like 'switch' and 'context' yourself. In fact you can even write a sensible ArrowApply instance. The problem is that it would have linear time complexity with respect to the number of instants that have passed, so it's not exactly useful." Notice that wires (just like all other arrowic automata in Haskell) switch all the time. Moving forward in time involves switching, so it's their very nature to do it. They could decide to switch to anything (provided the types fit) and they can observe the switching of other wires. There is no need for special library support for wires that manage a set of wires. Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.