[Haskell-cafe] Animated line art

Paul Johnson paul at cogito.org.uk
Sat Dec 6 12:05:00 EST 2008


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.


More information about the Haskell-Cafe mailing list