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 <[email protected]> wrote: > On Wed, Sep 30, 2009 at 9:54 AM, Peter Verswyvelen <[email protected]> > 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 [email protected] http://www.haskell.org/mailman/listinfo/haskell-cafe
