[Haskell-cafe] Splitting data and function declarations over multiple files

Job Vranish jvranish at gmail.com
Thu Oct 1 12:54:00 EDT 2009


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 <jvranish at 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/haskell@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 <bugfact at 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 <lrpalmer at gmail.com> wrote:
>>
>>> On Wed, Sep 30, 2009 at 9:54 AM, Peter Verswyvelen <bugfact at 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 at haskell.org
>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20091001/1175f14b/attachment.html


More information about the Haskell-Cafe mailing list