Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell inheritance, data, constructors

So I want to define multiple data classes for my Asteroids game/assignment:

data One = One {oneVelocity :: Velocity, onePosition :: Position, (((other properties unique to One)))}
data Two = Two {twoVelocity :: Velocity, twoPosition :: Position, (((other properties unique to Two)))}
data Three = Three {threeVelocity :: Velocity, threePosition :: Position, (((other properties unique to Three)))}

As you can see I have multiple data classes with some overlapping properties (velocity, position). That also meant that I had to give them different names per data class ("oneVelocity", "twoVelocity", ...).

Is there a way I can let these types of data extend something? I thought of using one datatype with multiple constructors, but some of these current data classes are very different and I don't thing they should reside in one data class with multiple constructors.

like image 447
The Coding Wombat Avatar asked Dec 06 '22 11:12

The Coding Wombat


2 Answers

You should probably use just a single data type for all of these, but parameterised on the specific details:

data MovingObj s = MovingObj
        { velocity :: Velocity
        , position :: Position
        , specifics :: s }

Then you can create e.g. asteroid :: MovingObj AsteroidSpecifics, but you can also write functions that work with any such moving object like

advance :: TimeStep -> MovingObj s -> MovingObj s
advance h (MovingObj v p s) = MovingObj v (p .+^ h*^v) s
like image 97
leftaroundabout Avatar answered Jan 08 '23 19:01

leftaroundabout


There is no inheritance in Haskell (at least, not the kind you associate with object-oriented classes). You just want composition of data types.

data Particle = Particle { velocity :: Velocity
                         , position :: Position 
                         }

-- Exercise for the reader: research the GHC extension that
-- allows all three of these types to use the same name `p`
-- for the particle field.
data One = One { p1 :: Particle
               , ... }
data Two = Two { p2 :: Particle
               , ... }
data Three = Three { p3 :: Particle
                   , ... }

Or, you can define a type that encapsulates the other properties, and let those be added to different kinds of Particles.

data Properties = One { ... } 
                | Two { ... }
                | Three { ... }

data Particle = Particle { velocity :: Velocity
                         , position :: Position
                         , properties :: Properties
                         } 

(Or see @leftaroundabout's answer, which is a nicer way of handling this approach.)

like image 23
chepner Avatar answered Jan 08 '23 20:01

chepner