[Haskell-cafe] animation application

Dennis Raddle dennis.raddle at gmail.com
Tue Jul 24 06:42:55 UTC 2018

Update: I may have gotten existential types to work.

I'm think of it like this: there's a type Object, which can be unwrapped
into different things depending on the type of the existential data.

data Object = forall s. { common :: Int, custom: s }

In purescript you define two types:

import Data.Exists

type ObjectInner s = ObjectInner { common :: Int, custom: s }

type Object = Exists ObjectInner

And then you can only access the innards of Object through the runExists
and mkExists functions.

I realized that I could think of the situation in a sort-of object oriented
way. I've got data, and an interface. I can define the interface as fields
with function values.

type ObjectInner s = ObjectInner { doSomething :: ObjectInner s -> IO (),
fetchSomething :: ObjectInner s -> Int, ... }

My whole application has a single list (or in Purescript, Array) of Object

bigPicture :: Array Object

I can define functions that use runExists to access the interface of any
given Object. My understanding is that the point of Existential types is
that the custom type is not supposed to escape its scope. In this method,
it seems that both the data and the functions for operating on it are
wrapped inside Object.

I think this is working for me. Needs a little more work.

On Mon, Jul 23, 2018 at 10:14 PM, Dennis Raddle <dennis.raddle at gmail.com>

> I'm working on an application for animating words, images, and shapes. I'm
> actually doing it in Purescript and it will become part of a math game that
> runs in the browser, but I'm asking my question on the Haskell list because
> the issues seem central to a functional/pure paradigm.
> Let's say that the things being animated are "objects." Objects could
> include photos, text, shapes, lines, etc. They can have fixed positions,
> colors, and other attributes, or their attributes can change over time.
> How do I compute attributes that change over time? In some cases, a
> function with a single argument, the current time, would suffice. I might
> want state, though -- perhaps an object's movement is pseudorandom and
> needs to refer to a seed and past position state.
> Objects might even need to observe each other's state. For instance,
> imagine we have two words, W1 and W2, and they move according to some
> stateful algorithm. Meanwhile we want to draw a line connecting their
> centers, so we need a line object L that can read the centers of W1 and W2.
> How do I represent the state of W1, W2, and L? I could define a general
> Object data type: (here there are no fields mentioned)
> data Object = W1  | W2  | L
> I will need state and the ability to customize the drawing and positioning
> functions, so to flesh out the fields of, say , W1.
> type St = StateT WholeScene IO
> data Object = W1 { leftEdge        :: Int
>                  , rightEdge       :: Int
>                  , topEdge         :: Int
>                  , bottomEdge      :: Int
>                  , computePosition :: W1 -> Time -> St W1
>                  , draw            :: W1 -> St ()
>                  ,  ... other state ...
>                  }
> Okay, so now I could define W2, which will be different in some ways,
> perhaps needing different state. But it will look a lot alike. It might
> have the same edge fields.
> In fact, all my objects will have similar position, color, etc.
> attributes. I certainly don't want to reinvent the wheel for everything.
> I also want objects to be able to read each other's state. Consider a
> basic positioning task: some object Obj1 keeps its left edge 100 pixels to
> the right of some other object's right edge. So the Obj1 function for
> computing position needs access to the other objects.
> Also consider that all these objects need to be put into a list together,
> to hold the state of the entire scene. They need to be members of the same
> class, and have a way to look each other up.
> One way to do this is have a single Object type with numerous
> constructors, and define similar functions on every constructor type (say,
> a function for accessing or setting the left edge).
> I also thought about having an Object be an existential type, and the
> fields that are custom to one object will be the existentially defined
> data. I actually implemented this in Purescript, but it got out of hand,
> probably due to my own weakness of understanding how existential types work.
> Any ideas?
> D
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20180723/71ea73e0/attachment.html>

More information about the Haskell-Cafe mailing list