Andrew Coppin wrote:
So I want some sort of sequencing primitives.
Sequencing generally suggests a monad. something = do { action1; delay
10; action2}
I had a go at writing what I thought the interface might look like.
(Fortunately, I made no attempt to *implement* it - otherwise I would
doubtless have wasted huge amounts of time implementing something that
isn't designed right yet!) Unfortunately Haskell doesn't really
provide a way to write an "interface", and then write the
implementation behind it seperately somewhere else. So the "code" I
wrote wasn't actually compilable at all, but it was useful to sketch
something out.
When I do this I generally write functions like foo = error "foo: Not
implemented yet"
My initial idea was that I could have some kind of monad for
controlling adding and removing stuff. The monad could provide an
"add" action that adds a visual object to the frame and returns a
unique ID. Then you could have a "remove" action that removes the
specified ID again. And a "wait" action that makes the display stay
the same for so many seconds. (But the visual objects may internally
be animated.)
I'd suggest that each object has its own action to animate it. You will
need to write a custom monad to interleave actions. See
http://www.cs.chalmers.se/~koen/pubs/jfp99-monad.ps for something along
the right lines.
Then I hit upon the idea that maybe one thread of control could
"spawn" a second one - so that for example one thread could generate a
bunch of snowflakes raining down the screen while a seperate thread
rotates a geometric figure in the center. Or something.
Sounds right.
Of course, these "threads" have no need (or use) for actually running
concurrently - they are only "concurrent" in the sence that they both
affect the same frame, rather than their actions happening one after
another on consecutive frames.
Next I got to thinking that maybe these threads of control might need
to communicate for synchronisation. E.g., when a rotating line reaches
90° with another line, a signal is sent to another thread, which then
adds another visual element or stops the animation or something. The
parent thread *could* algebraicly _compute_ what time this will
happen, but sending a signal is much simpler. (E.g., if you change the
speed of an animation, the threads still stay synchronised without you
having to remember to adjust parameters in your calculations all over
the place...)
Yup. I did exactly this, albeit for a very different application.
Unfortunately the code belongs to my employer so I can't post it. But
if you look at the paper above and also read about the "ContT" monad you
will get the right idea. Its a bit mind-bending, but you suspend a
thread by getting its continuation (using callCC) and stuffing it into
whatever data structure is being used to hold pending threads (e.g. a
semaphore queue).
Or you could use the existing concurrent threads mechanism, which is
kludgier but less work.
There's still one little problem though. The "threads of control" are
for sequencing stuff. They are inherantly discrete; *add* this thing,
*remove* this other thing, *send* this signal, *wait* to receive a
signal, etc. But something like, say, rotating a line, is inherantly
continuous. So there's a discrete system for sequencing stuff - which
I seem to have worked out fairly well - and there also needs to be a
continuous system for doing all the things with are smooth functions
of time.
Thats where Reactive stuff comes in.
So maybe the continuous stuff should just be a type alias to a regular
Haskell function? Ah, but wait... I said I might want to send a signal
when an animation reaches a specific stage, right? So these
"functions" need to do more than just map time to some other variable;
they need to be able to send signals. And hey, actually, what are the
chances of a time sample exactly lining up with the instant that the
notable event occurs? How do I want to handle that?
Events are part of reactive frameworks.
Paul.
_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe