haskellfunctional-programmingfrpnetwire

Using netwire's periodic vs. at wires


I'm trying to write a framework for real-time interactive graphics in Haskell. I've been trying to get a handle on things by using Netwire 5, but I don't seem to have a good handle on how things "depend" on one another. For example, the following code should produce val for two seconds before switching to (val + 1), and then continuing on indefinitely.

someWire :: Num a => a -> Wire s e m a a
someWire x = (-->) ((pure x) &&& (periodic 2) >>> until) (someWire (x + 1))

However, this creates some sort of memory leak where my program stalls and just keeps allocating memory until something on my system crashes. Alternatively, this definition

someWire :: Num a => a -> Wire s e m a a
someWire x = (-->) ((pure x) &&& (at 2) >>> until) (someWire (x + 1))

behaves the way that I expect it to: count from val onwards having the value change every two seconds. Can someone please explain this behavior?


Solution

  • The key insight is that periodic produces an event immediately.

    Hence, when we go to produce a value from this wire, we have to evaluate it into the following:

    someWire x
    (-->) ((pure x) &&& (periodic 2) >>> until) (someWire (x + 1))
    (-->) (pure (x, Event _) >>> until) (someWire (x + 1))
    (-->) *inhibition* (someWire (x + 1))
    someWire (x + 1)
    

    Since this isn't tail recursive, the garbage collector isn't allowed to clean up the previous instances that are allocated for the wire and we run out of memory (instead of getting an infinite loop).