
Hi Haskell'ers, I'm trying, more as a first excercise in Haskell than anything else, to code a simulation framework in Haskell. A simulation is a bunch of simulation state consisting of constituents (e.g. physical entities like a ball or properties like temperature), on which agents (e.g. simulated humans) in the system can do activities. Activities have a certain duration, and define how the simulation progresses. The simulator framework should just define the basics to maintain a normal representation of time and of cause and effect, i.e. make sure that the state evolves through the application of the activities in the right order. In a later step I will add "laws", which transform activities when they overlap or conflict (e.g. two drive activities leading to collision). I've run into the following problem. I defined a class that allows to define activities on constituents: class Activity a c where start :: c -> a -> Time --start of the activity (this isn't actually dependent on c, I guess) end :: c -> a -> Time --end of the activity delta :: a -> Time -> c -> c --how the constituent is changed at the given time Two parameter type class because some activities are only applicable to certain constituents: instance Activity Paint Ball where instance Activity Move Ball where instance Activity Paint Wall where but you can't move a wall for example, so no instance for Move Wall. My question is: How can I now represent the state of the simulation (i.e. all activites on all constituents). E.g. a list of activities won't do since the list is heterogeneous (i.e. [Paint Ball White, Move Ball (2,0)]) I know about existentials, but I'm at a loss at how to implement the "wrapper" datatype that is exemplified on http://www.haskell.org/hawiki/ExistentialTypes since my class has two parameters, in fact I'm at a loss at how to use existentials here completely. Then, how could I go back from the "general" lists (or whatever datatype) of [a]'s and [c]'s, to a list of [([a],c)] of all activities a that are applicable to a certain constituent c? I can't seem to be able to use the Typeable class for example, since this can not "cast" to typeclasses, only to concrete types (I think...). What I initially liked about this idea is that it can be encoded in the typesystem which activities apply to which consituents, but now it seems like I will have to encode it in the simulation framework more directly (i.e. giving each consituent a String name to encode its "type"). More straightforward ways of modelling this problem (avoiding multiple type class parameters and existentials :) )are also welcome. thanks for any pointers, Kurt

Dear Kurt,
I'm trying, more as a first excercise in Haskell than anything else, to code a simulation framework in Haskell.
I don't have the time to respond to your mail in detail right now, but you might want to have a look at the work on Fran (functional reactive animation), FRP (Functional Reactive Programming), and Yampa, all very much related to the application area you're interested in. E.g. see http://www.haskell.org/frp/ All the best, /Henrik -- Henrik Nilsson School of Computer Science and Information Technology The University of Nottingham nhn@cs.nott.ac.uk This message has been checked for viruses but the contents of an attachment may still contain software viruses, which could damage your computer system: you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation.

Hello Kurt, Friday, December 8, 2006, 1:11:35 PM, you wrote:
I'm trying, more as a first excercise in Haskell than anything else, to
class Activity a c where
seems like your goes from OOP world? :) type classes are pretty rare birds in Haskell programs. There are other ways to implement such functionality: http://haskell.org/haskellwiki/OOP_vs_type_classes btw, i also suggest looking into sources of Base and MissingH libraries to see examples of good programming style -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On 12/8/06, Kurt Schelfthout
Hi Haskell'ers, <snip>
class Activity a c where start :: c -> a -> Time --start of the activity (this isn't actually dependent on c, I guess) end :: c -> a -> Time --end of the activity delta :: a -> Time -> c -> c --how the constituent is changed at the given time <snip> How can I now represent the state of the simulation (i.e. all activites on all constituents). E.g. a list of activities won't do since the list is heterogeneous (i.e. [Paint Ball White, Move Ball (2,0)]) I know about existentials, but I'm at a loss at how to implement the "wrapper" datatype that is exemplified on http://www.haskell.org/hawiki/ExistentialTypes since my class has two parameters, in fact I'm at a loss at how to use existentials here completely.
An existential type will do roughly what you want. I prefer GADT syntax here: data AnyActivity where AnyActivity :: Activity a c => a -> c -> AnyActivity Then, given an activity/constituent pair like, say, Move (2,0) and Ball, you can say: AnyActivity (Move (2,0)) Ball to package the pair. The resulting object has type AnyActivity, and can be stored in a list with other AnyActivities. You can write variations on your class methods that work on the packaged datatype: startAny :: AnyActivity -> Time startAny (AnyActivity a c) = start c a endAny :: AnyActivity -> Time endAny (AnyActivity a c) = end c a deltaAny :: AnyActivity -> Time -> AnyActivity deltaAny (AnyActivity a c) time = AnyActivity a (delta a time c)
Then, how could I go back from the "general" lists (or whatever datatype) of [a]'s and [c]'s, to a list of [([a],c)] of all activities a that are applicable to a certain constituent c? I can't seem to be able to use the Typeable class for example, since this can not "cast" to typeclasses, only to concrete types (I think...).
I'm not exactly sure what you want here. Since activities of a different type can affect the same constituent, it's not possible to go from a constituent c to a list of activities. You could, for example, find all the AnyActivity wrappers that contain a given constituent, if you added Typeable and Eq constraints: -- I didn't actually test this code data AnyActivity where AnyActivity :: (Activity a c, Typeable c, Eq c) => a -> c -> AnyActivity activitiesAffecting :: (Eq c, Typeable c) => c -> [AnyActivity] -> [AnyActivity] activitiesAffecting c [] = [] activitiesAffecting c (a@(AnyActivity _ c'):as) | c `eq` c' = a : activitiesAffecting c as | otherwise = activitiesAffecting c as where t `eq` t' | Just t'' <- cast t' = t == t'' | otherwise = False Extracting the original a and c used in a wrapper can be done as well, if you also include a Typeable constraint on a.
More straightforward ways of modelling this problem (avoiding multiple type class parameters and existentials :) )are also welcome.
Without seeing more of your goals, I'm not sure I can suggest anything else. I've found myself writing wrapper code like this before, and it doesn't have to end up completely confused and unusuable. On the other hand, it does feel somewhat inelegant to me - looking at FRP, for instance, might give you some good ideas for other approaches. /g -- It is myself I have never met, whose face is pasted on the underside of my mind.
participants (4)
-
Bulat Ziganshin
-
Henrik Nilsson
-
J. Garrett Morris
-
Kurt Schelfthout