160 likes | 300 Vues
FunWorlds functional programming and virtual worlds FunWorlds/HOpenGL ( or: the story continues). IFL 2002, Madrid, September 2002 Claus Reinke University of Kent at Canterbury. http://www.cs.ukc.ac.uk/people/staff/cr3/FunWorlds/. IFL 2001: FunWorlds/VRML
E N D
FunWorldsfunctional programmingand virtual worlds FunWorlds/HOpenGL(or: the story continues) IFL 2002, Madrid, September 2002 Claus Reinke University of Kent at Canterbury http://www.cs.ukc.ac.uk/people/staff/cr3/FunWorlds/
IFL 2001: FunWorlds/VRML • Haskell-embedded DSL, compiled to VRML browser Scene.wrl Scene.hs import VRML scene = scene_1(time)untilevent(time) thenscene_2(time) main = toFile "scene.wrl" scene Script browse run sensor routes eventIns eventOuts Haskell+library VRML+ECMAScript FunWorlds: Motivation/Background Explore language design issues • in functional & concurrent programming • in 3d graphics & animation(HCIs) • concise high-level specifications (Fran-style DSEL, reactive behaviours), portable 3d graphics (VRML scene graphs & browsers), animation (time sensor, events & ECMAScript), reactivity (sensor nodes, events & more scripting) • access to functional programming ideasmostly limited to compile-time even recursion tricky
FunWorlds/HOpenGL Same motivation, but completely new system • don't try to re-implement functional RTS in Java/ ECMAScript, re-implement graphics in Haskell • build on top of HOpenGL (portable graphics standard) • Also: Take another look at Fran's design • convincing ideas, but persistent problems in practice • modularity and performance issues • implementations got increasingly complex/fragile • concepts clear, but language core hard to pin down, always new "primitives" or abstractions just around the corner (the latter sometimes hide design issues that could be avoided) • design constant, abstractions/implementations evolve • Can we change the core design instead?
fp predicate a a until/then Behaviours Events snapshot t t stepper Fran Behaviour acontinuous time dependent values Event astreams of time-stamped values Fran programs: mutually recursive integral equations, interspersed with reactivity and with fp
Problems with Fran? (1) • "direct translation of differential/integral equations for control systems".. • numerical approximation sometimes not good enough at real-time sampling rates; external factors can influence simulation outcome! • original approach centers around idealised concepts: • core concepts fixed (known from TBAG and ActiveVRML times) • devise denotational and idealised semantics • approximate by functional implementations • if it doesn't work, try to improve implementations • repeated evaluation -> memoization; CAF leaks -> GC help • surprising space-/time-leaks • if it isn't nice, try to layer abstractions on top • recent variations (Yale‘s realtime and embedded FRP variants) • take operational aspects seriously, start with operational semantics • tune the design to guarantee performance
a untilB b te Problems with Fran? (2) • Monolithic approach to basic concepts • Behaviours: functions from alltimes to values Time -> a • Events: streams of all event (non-)occurrences[(Time,Maybe a)]) • User argument: external events, the start time (lbp u, integral u a) on closer inspection, all of these are at odds with Fran‘s general focus on compositional modeling (feels more like weaving a carpet of infinite strings than simple composition)! The history of functional i/o taught us to favour stepwise/local approaches over monolithic/global ones!
Where to, then, with FunWorlds? • start with 3d scene graphs, a la VRML • add reactive behaviours, a la Fran, but • get rid of global time (but permit local clocks), replace monolithic/global descriptions with stepwise/local descriptions • a behaviour can be sampled to deliver a current value and a residual behaviour (note: no time parameter, no separate notion of events, no need to "age" behaviours) • emphasise both behaviour descriptions and their sampling, enable specification of shared sampling (instead of implementation-level memoization) • describeconcurrency and communication more explicitly, using ideas from process calculi • translate the resulting "communicating concurrent behavioural scene graphs" into GLUT callbacks and instructions for the OpenGL rendering pipeline • fiddle with design until satisfied (never!-)
FunWorlds FRPsyntax/feature overview • scene graphs (standard) • reactive behaviours • constant behaviours; lifting of function application, arithmetic, boolean operations, conditional, .. • Beh (Maybe a) and Beh Bool for events • reactivity (Until/ThenM/ThenB) • behavioural-level let to express sharing (LetB) • base representation in terms of Then/Snap • concurrency and communication • behavioural channels (transparent broadcasting of sample values, observers track sources) NewChannel :: String->(Ch a->Beh a)->Beh a Source :: Beh a->Ch a->Beh a Observe :: a->Ch a->Beh a
Planet ..imports.. scene :: Ch (Maybe Char) -> Scene scene keyb = SB $ groupB [ sun, planet ] where sun = coloredShapeB whiteB $ sphereB 1 planet = rotateB (rotationB year (vector3B 0 1 0)) $ translateB (vector3B 2 0 0) $ rotateB (rotationB day (vector3B 0 1 0)) $ coloredShapeB greenB $ sphereB 0.2 year, day :: Beh GLdouble year = integral (ifB (keyPressed (=='y')) 5 (ifB (keyPressed (=='Y')) (-5) 0)) day = integral (ifB (keyPressed (=='d')) 10 (ifB (keyPressed (=='D')) (-10) 0)) key = Observe Nothing keyb keyPressed p = lift1 (maybe False p) key main :: IO () main = start (KeyBoard scene)
Juggle ..imports.. scene = groupB [flight cycle redB, flight cycle2 greenB, flight cycle3 blueB] where time, xbase, ybase :: GLdoubleB time = integral 0.05 (xbase,ybase) = (-1.4, -1) base = vector3B xbase ybase 0 flight cycle colorB = translateB cycle $ coloredShapeB colorB $ sphereB 0.3 cycle2 = base `Until` ((x .>. 1) `then_` cycle) cycle3 = base `Until` ((x .>. 1) `then_` cycle2) x,y :: GLdoubleB x = xbase + (1/2*time) y = ybase + (8/5*time) + integral (-1/50*time) cycle = vector3B x y 0 `Until` ((y .<. ybase) `then_` (vector3B (-x) y 0 `Until` ((y .<. ybase) `then_` cycle))) main = start $ SB scene
n-floor lift (outline) keyboard Beh (Maybe Char) keyCh pending requests Beh [GLdouble] pCh rCh lift position Beh GLdouble
FunWorlds/HOpenGL implementation overview behavioural channels Maybe Char keyboardFunc keyboard observers sources scene graph behavioural scene graph GL instr. samples displayFunc screen residuals trigger time idleFunc transmit sample FunWorlds/FRP sampling cycle FunWorlds/HOpenGL rendering GLUT main loop
Closely related work Elliot, surveying Fran implementation options in 1998, chose stream transformers instead of "residual behaviours", because of conflicts with time transformations and memoization. Fran offers snapshot/afterE. Yale A) realtime FRP, embedded systems FRP • restricted languages to guarantee performance [ICFP 2001], or to match target system environment [PADL 2002] • operational semantics, pragmatic approach Yale B) arrows-based FRP [Haskell WS & PPDP 2002] • full Haskell embedding, but no direct access to behaviours, instead use of behaviour transformers (with arrows and syntax) • reported better performance characteristics • global time less accessible, focus on routing information between behaviours
Conclusions • FunWorlds project is work in progress • HOpenGL version & new FRP just started • Significant simplification of Fran concept set, addition of situated concurrency and beh. channels • Experience so far • Still permits Fran-style programming, but more modular, and makes reactive programming easier • Simple operational semantics -> uncomplicated implementation, no performance surprises yet • Need more non-trivial, well-documented examples (juggle, n-floor lift [ThompsonJFP],..) • Snapshot available on request, but still lacks: • Basic documentation (tutorial) • Richer scenegraph