Opps, errors, it should be more like: moveBall (Vector2 x y) (Ball ...) = ... movePaddle (Vector2 x y) (Paddle ...) = ...
-- selection actions for Ball instance Actor Ball where mkActor this = let pos' = getBallPosition this move' v = mkActor $ moveBall v this in Actor pos' move' -- selection actions for Paddle instance Actor Paddle where mkActor this = let pos' = getPaddlePosition this move' v = mkActor $ movePaddle v this in Actor pos' move' Hmm, I bet some generics, or template haskell could clean up the extra boilerplate associated with this technique. - Job On Thu, Oct 1, 2009 at 11:35 AM, Job Vranish <jvran...@gmail.com> wrote: > Along the projection/co-algebra lines (I actually didn't know that's what > they were called until today :) yay for learning new things!) > > How about something like this: > > -- Define "prototypes" for your class of actions here > data Actor = Actor {pos::Vector2 Float, move::Vector2 Float -> Actor} > > -- simple class that selects your actions based on type > class ActorClass a where > mkActor :: a -> Actor > > -- object types > data Ball = Ball ... -- stuff > data Paddle = Paddle ... -- stuff > data Wall = Wall ... -- suff > > -- Functions for working with objects > getBallPosition (Ball ...) = ... > getPaddlePosition (Paddle ...) = ... > > moveBall (Ball ...) = ... > movePaddle (Ball ...) = ... > > -- selection actions for Ball > instance Actor Ball where > mkActor this = let > pos' = getBallPosition this > move' v = moveBall this > in Actor pos' move' > > -- selection actions for Paddle > instance Actor Paddle where > mkActor this = let > pos' = getPaddlePosition this > move' v = movePaddle this > in Actor pos' move' > > > Base off a technique I ran across here: > http://www.mail-archive.com/hask...@haskell.org/msg04513.html > > Also, a useful wikipage for doing OO things in haskell: > http://www.haskell.org/haskellwiki/OOP_vs_type_classes > > - Job > > > On Thu, Oct 1, 2009 at 4:45 AM, Peter Verswyvelen <bugf...@gmail.com>wrote: > >> I'm not sure if I understand what you mean with this co-algebraic >> approach, but I guess you mean that functions - like move - don't work >> directly on any datatype; you need to provide other functions that give >> access to the data. But that's basically what type classes do no? And that's >> also related to my earlier post of "strong duck typing" in Haskell. >> At least also in C#, that's the way I usually write code that works on any >> type, just make an interface or pass in a delegate. I also know that my OO >> background keeps pushing me in the wrong direction when it comes to Haskell >> ;-) >> >> The collision handling approach is always interesting :) In OO this is >> usually solved using multi-methods or visitors: >> http://en.wikipedia.org/wiki/Multiple_dispatch. What I usually did in old >> games of mine to handle collisions is not look at the type, but at the >> "collision specific features" of a type (which are again functions that >> extract information from the object), and that is most likely again the >> co-algebraic approach? >> >> On Wed, Sep 30, 2009 at 9:15 PM, Luke Palmer <lrpal...@gmail.com> wrote: >> >>> On Wed, Sep 30, 2009 at 9:54 AM, Peter Verswyvelen <bugf...@gmail.com> >>> wrote: >>> > I guess this is related to the expression problem. >>> > Suppose I have a datatype >>> > data Actor = Ball ... | Paddle ... | Wall ... >>> > and a function >>> > move (Ball ...) = >>> > move (Paddle ...) = >>> > move (Wall ...) = >>> > in Haskell one must put Actor and move into a single file. >>> > This is rather cumbersome if you work with multiple people or want to >>> keep >>> > the files small and readable. >>> > Surely it is possible to use type classes, existentials, etc to split >>> the >>> > data type into multiple ones, but that's already advanced stuff in a >>> sense. >>> >>> You can do it without type classes and existentials. The >>> functionality you want is already supported by Haskell, you just have >>> to let go of your syntactical expectations. The trick is that you >>> should rewrite your data type not as an algebra (a set of >>> constructors), but as a coalgebra (a set of projections). >>> >>> Let's say your two open functions are: >>> >>> move :: Actor -> Actor >>> isAlive :: Actor -> Bool >>> >>> This gives rise to the definition of an Actor type: >>> >>> data Actor = Actor { move :: Actor, isAlive :: Bool } >>> >>> And then the alternatives of your open data type are just values of type >>> Actor: >>> >>> ball :: Vector -> Vector -> Actor >>> ball pos vel = Actor { >>> move = ball (pos + vel) vel, >>> isAlive = True >>> } >>> >>> etc. >>> >>> This trick works well until you get to the encoding of functions that >>> pattern match on multiple Actors at the same time. As far as I can >>> tell, that cannot be encoded in this style in any reasonable way. >>> Such functions must be rephrased in a coalgebraic style; i.e. instead >>> of asking about constructors, using projection functions it knows are >>> available. >>> >>> So for example instead of implementing "collide" by asking about >>> pairs, add functions which report a shape function and a normal, or >>> whatever your collide algorithm needs from shapes. >>> >>> You would probably end up having to do this anyway even with your >>> proposed extension, because watch: >>> >>> partial data Actor = Ball ... >>> >>> collide (Ball ...) (Ball ...) = ... >>> collide (Ball ...) x = ... >>> >>> We don't know about any other constructors, so the second line has to >>> contain a pattern-free x. So you would have to use projection >>> functions to get any information about it, exactly as you would when >>> you're writing in the coalgebraic style. >>> >>> So, Yes! Haskell can do that! >>> >>> Luke >>> >> >> >> _______________________________________________ >> Haskell-Cafe mailing list >> Haskell-Cafe@haskell.org >> http://www.haskell.org/mailman/listinfo/haskell-cafe >> >> >
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe