
I'm currently working on idioms for game programming using FRP. After going through several representations of physics as arrows[1] I decided that physics objects must not be implemented as arrows, because introducing new arrows in the middle of a computation[2] leads to ugly pain. So far the best approach I have is to represent the physics world as a single object World, with a function
integrate :: TimeStep -> World -> World
But I can't figure out a good way to represent bodies in this world. I considered:
newBody :: (Position,Velocity) -> World -> (Body,World)
Where Body is an ADT with an internal representation of an Integer or something. The problem with this is that (1) there is no way to guarantee that a Body actually exists in a World (which is a minor but still annoying issue), and (2) that there's a possibility that you could make a Body in one world and use it in another and there would be no way to detect the error. (2) could be solved using an internal representation of Data.Unique, but (1) still remains a problem. And as long as the function
deleteBody :: Body -> World -> World
exists, it will always remain a problem. Are there any clever idioms I can use for this interface or implementation? Is there a way to store the data for bodies along with the Body object instead of with the world in a way that the relationships between them respect different generations of the World (through integrate)? Any other ideas? Thanks, Luke [1] Once as SF () (Position,Velocity), and again as SF PhysIn PhysOut where PhysIn = (Impulse,Momentum) and PhysOut = (Position,Velocity). [2] Using the arrow joinSF :: SF (Event (SF [a] a)) [a], and other similar style functions taking streams of SF events...

On Fri, 30 Nov 2007, Luke Palmer wrote:
But I can't figure out a good way to represent bodies in this world. I considered:
newBody :: (Position,Velocity) -> World -> (Body,World)
Where Body is an ADT with an internal representation of an Integer or something. The problem with this is that (1) there is no way to guarantee that a Body actually exists in a World (which is a minor but still annoying issue), and (2) that there's a possibility that you could make a Body in one world and use it in another and there would be no way to detect the error.
Is it ok to have phantom types for Body and World? This would work if the number of worlds is fixed at compile time. newBody :: (Position,Velocity) -> World worldId -> (Body worldId, World worldId)

I think your integrate function looks like a good idea:
integrate :: TimeStep -> World -> World
For bodies, I think you should have a BodyID type, and then to add a body to the world you could have a function:
newBody :: (Position, Velocity) -> World -> (BodyID, World)
To delete a body:
deleteBody :: BodyID -> World -> World
So your World type will need to contain all of the bodies "inside" it, something like this: data World = World { gravity :: Vector, bodies :: [(BodyID, (Position, Velocity, BodyProperties))] This is pretty much the way things are done in the FRP paper "The Yampa Arcade", where they use an "Identity List" where the type ILKey = Int. See section 5.5 of the paper: http://www.haskell.org/yale/papers/haskell-workshop03/index.html

There seems to be three salient benefits of using arrows, as I read the Abstract and Introduction of Benjamin Lerner, "Arrow Laws and Efficiency in Yampa", 2003, http://zoo.cs.yale.edu/classes/cs490/03-04a/benjamin.lerner/ 1) The discipline of using arrows assists in avoiding space-leaks "The reasons underlying this...primarily stemmed from the availability of signals as first-class values." [the "ugly pain" you experience up front saves you chronic pain later. Self-discipline is the key to a happy life.] 2) Arrow syntax analogous to circuit diagrams => Arrow semantics analogous to signal processing [a mental/software model that resembles a physical model helps intuitive reasoning by analogy] 3) Satisfying arrow laws guarantees soundness of signal function type [you can have faith in the results of your simulation if the basic plumbing has been stress-tested in advance.] * The stuff in brackets is my own interpretation The overall impression I get is that using arrows makes simulations more scalable as overall simulation complexity increases. It will be good to get another use-case for this domain of application. Luke Palmer wrote:
I'm currently working on idioms for game programming using FRP. After going through several representations of physics as arrows[1] I decided that physics objects must not be implemented as arrows, because introducing new arrows in the middle of a computation[2] leads to ugly pain.
So far the best approach I have is to represent the physics world as a single object World, with a function
integrate :: TimeStep -> World -> World
But I can't figure out a good way to represent bodies in this world. I considered:
newBody :: (Position,Velocity) -> World -> (Body,World)
Where Body is an ADT with an internal representation of an Integer or something. The problem with this is that (1) there is no way to guarantee that a Body actually exists in a World (which is a minor but still annoying issue), and (2) that there's a possibility that you could make a Body in one world and use it in another and there would be no way to detect the error.
(2) could be solved using an internal representation of Data.Unique, but (1) still remains a problem. And as long as the function
deleteBody :: Body -> World -> World
exists, it will always remain a problem. Are there any clever idioms I can use for this interface or implementation? Is there a way to store the data for bodies along with the Body object instead of with the world in a way that the relationships between them respect different generations of the World (through integrate)? Any other ideas?
Thanks, Luke
[1] Once as SF () (Position,Velocity), and again as SF PhysIn PhysOut where PhysIn = (Impulse,Momentum) and PhysOut = (Position,Velocity).
[2] Using the arrow joinSF :: SF (Event (SF [a] a)) [a], and other similar style functions taking streams of SF events... _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Nov 30, 2007 7:26 PM, Dan Weston
There seems to be three salient benefits of using arrows, as I read the Abstract and Introduction of Benjamin Lerner, "Arrow Laws and Efficiency in Yampa", 2003, http://zoo.cs.yale.edu/classes/cs490/03-04a/benjamin.lerner/
1) The discipline of using arrows assists in avoiding space-leaks "The reasons underlying this...primarily stemmed from the availability of signals as first-class values." [the "ugly pain" you experience up front saves you chronic pain later. Self-discipline is the key to a happy life.]
I experienced the chronic pain in my initial comonadic implementation of FRP. It was pretty, but ran in quaadratic time :-(. To be clear, I am not abandoning arrows in FRP. I am abandoning using an arrow to represent *each* object in favor of moving objects into the value level rather than the signal level. i.e. the following dies: ball :: Position -> Velocity -> SF PhysIn PhysOut ... In favor of game = proc () -> do rec world <- integrate initWorld -< trajectory world ... I have an idea for an external solution though that I'm going to play with now. I'll report on how it goes :-) Luke
participants (4)
-
Bit Connor
-
Dan Weston
-
Henning Thielemann
-
Luke Palmer