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

Luke Palmer lrpalmer at gmail.com
Wed Sep 30 15:15:19 EDT 2009


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


More information about the Haskell-Cafe mailing list