
On 12/19/08, Conal Elliott
As long as we use not just the arrow abstraction but also *arrow notation*, I don't know how we'll ever be able to get an efficient implementation, in which portions of computed signals get recomputed only when necessary. And probably the Arrow abstraction itself is a bit too restrictive, given that it disallows any conditions on its type arguments. So I've been noodling some about formulations of signal functions that don't fit into the standard arrow discipline.
Paul (Hudak) and I recently worked on a notion called Causal Commutative Arrows, which actually gave a very good optimization result for Yampa like arrows. One notable feature is that all programs normalize, regardless of whether they were originally written using the Arrow combinators or translated from Arrow notations. I recently give a talk at NEPLS on this, the slides are here: http://www.cs.yale.edu/homes/hl293/download/NEPLS-talk.pdf Due to the use of arrow laws, our technique remains fully abstract without committing to any concrete representation of arrows or signals/streams. The re-computation problem is another issue though. I fully agree with Henrik's comment on push v.s. pull. But if one really wants to avoid re-computation at all efforts, here is one possibility: pass :: SF a b -> SF (Maybe a) (Maybe b) It'll only invoke the given SF when the input is Just something, and do nothing otherwise. Coupled with hold, it shall lead to efficient implementation that avoids re-computation when inputs don't change. Intuitively it's like selectively turning on/off part of a circuit according to inputs, which naturally falls in the ArrowChoice class. Also one has to extract the implicit time from the inplementation and make it an explicit input in order for this to be semantically sound. -- Regards, Paul Liu Yale Haskell Group http://www.haskell.org/yale