Transcript Document
FunWorlds
functional programming
and virtual worlds
FunWorlds/HOpenGL
(or: the story continues)
http://www.cs.ukc.ac.uk/people/staff/cr3/FunWorlds/
IFL 2002, Madrid, September 2002
Claus Reinke
University of Kent at Canterbury
FunWorlds: Motivation/Background
Explore language design issues
– in functional & concurrent programming
– in 3d graphics & animation (HCIs)
IFL 2001: FunWorlds/VRML
– Haskell-embedded DSL, compiled to VRML
Scene.hs
Scene.wrl
browser
– concise high-level specifications (Fran-style
portable 3d graphics
, animation
, reactivity
import VRML
scene = DSEL, reactive behaviours),
Script
scene_1(time) until
(VRML
scene
graphs
& browsers)
browse
run
event(time)
(time sensor, events &sensor
ECMAScript)
then scene_2(time)
main = toFile
(sensor nodes, events & more scripting)
"scene.wrl"
routes
scene
eventIns eventOuts
– access to functional programming ideas
mostly limited to compile-time even recursion
Haskell+library
VRML+ECMAScript
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
Also:standard)
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
Fran
fp
predicate
a
Behaviours
a
Events
until/then
t
snapshot
stepper
t
Behaviour a
continuous time
dependent values
Event a
streams of timestamped 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
Problems with Fran? (2)
Monolithic approach to basic concepts
– Behaviours: functions from all times 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)!
a
untilB
te
b
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)
• describe concurrency 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 FRP
syntax/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
..imports..
Planet
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)
..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
Juggle
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
keyboardFunc
keyboard
observers
Maybe Char
displayFunc
screen
behavioural
channels
idleFunc
time
implementation overview
sources
behavioural
scene graph
samples
scene GL
graph instr.
residuals
trigger
sample
transmit
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
FunWorlds FRP
operational semantics – part 1
FunWorlds FRP
operational semantics – part 2