On 12/8/06, Kurt Schelfthout <[EMAIL PROTECTED]> wrote:
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.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to