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.
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
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.)
Related
I'm new to Haskell and trying to do something which I'm sure is easy but I'm not seeing the right way to do it.
What I want is a list of values of a particular typeclass, but different types of that typeclass. Eg:
class Shape a where
area :: a -> Double
numVertices :: a -> Integer
data Triangle = Triangle {...}
data Square = Square {...}
instance Shape Triangle where ...
instance Shape Square where ...
x = [Triangle (...), Square (...)]
I'm getting a compiler error because the list has different types. What's the right way to do what I'm trying to do here? The only thing I've been able to come up with is doing something like this:
data WrappedShape = WrappedShape {
getArea :: () -> Double
, getNumVertices :: () -> Integer
}
wrap s = WrappedShape {
getArea = \ () -> area s
, getNumVertices = \ () -> vertices s
}
x = [wrap (Triangle (...)), wrap (Square (...))]
This works, but it's heavy on boilerplate, since I have to effectively define Shape twice and with differently-named members. What's the standard way to do this sort of thing?
If you just need a few different shapes, you can enumerate each shape as a constructor, here is a example:
data SomeShapes = Triangle {...}
| Square {...}
instance Shape SomeShapes where
area (Triangle x) = ...
area (Square x) = ....
now you can put them in a list, because they are same type of SomeShapes
[Triangle {...}, Square {...}]
Your wrapped type is probably the best idea.
It can be improved by noting that, in a lazy language like Haskell, the type () -> T essentially works like the plain T. You probably want to delay computation and write stuff like let f = \ () -> 1+2 which does not perform addition until the function f is called with argument (). However, let f = 1+2 already does not perform addition until f is really needed by some other expression -- this is laziness.
So, we can simply use
data WrappedShape = WrappedShape {
getArea :: Double
, getNumVertices :: Integer
}
wrap s = WrappedShape {
getArea = area s
, getNumVertices = vertices s
}
x = [wrap (Triangle (...)), wrap (Square (...))]
and forget about passing () later on: when we will access a list element, the area/vertices will be computed (whatever we need). That is print (getArea (head x)) will compute the area of the triangle.
The \ () -> ... trick is indeed needed in eager languages, but in Haskell it is an anti-pattern. Roughly, in Haskell everything has a \ () -> ... on top, roughly speaking, s o there's no need to add another one.
These is another solution to your problem, which is called an "existential type". However, this sometimes turns into an anti-pattern as well, so I do not recommend to use it lightly.
It would work as follows
data WrappedShape = forall a. Shape a => WrappedShape a
x = [WrappedShape (Triangle ...), WrappedShape (Square ...)]
exampleUsage = case head x of WrappedShape s -> area s
This is more convenient when the type class has a lots of methods, since we do not have to write a lot of fields in the wrapped type.
The main downside of this technique is that it involves more complex type machinery, for no real gain. I mean a basic list [(Double, Integer)] has the same functionality of [WrappedShape] (list of existentials), so why bother with the latter?
Luke Palmer wrote about this anti-pattern. I do not agree with that post completely, but I think he does have some good points.
I do not have a clear-cut line where I would start using existentials over the basic approach, but these factors are what I would consider:
How many methods does the type class have?
Are there any methods of the type class where the type a (the one related to the class) appears not only as an argument? E.g. a method foo :: a -> (String, a)?
I'm using Haskell to make a game, (this is an assignment, so don't judge me) but I'm facing a problem regarding data types.
So what I want is a data type Entity which has a location, velocity, angle and a rotation speed. A record works very well for this idea:
data Entity = Entity {
location :: Vector,
velocity :: Vector,
angle :: Float,
rotation :: Float
}
Now I want instances of Entity, namely Player Rock Pickup and Bullet. But Players Rocks and Bullets must have an extra field, namely health :: Int, and Pickup must have another extra field, namely pickupType :: PickupType.
But I have certain methods which I want to work on any Entity type. For example:
move :: Entity -> Entity
move e#(Entity {location, velocity, angle, rotation}) = e {location = location + velocity, angle = angle + rotation}
I have no idea how to do this or if this is even possible. I wouldn't understand why if it isn't possible, since this is definitely possible in other languages.
Some attempts and why they aren't quite what I desire:
Attempt 1:
type Player = Player {
e :: Entity,
health :: Int
}
This works, but it is really ugly. This, for example, is how you would move a Player:
movePlayer :: Player -> Player
movePlayer p#(e) = p {e = move e}
Which is just really ugly.
Positives:
Easy to create the abstract class.
Easy to create instances.
Easy abstract methods.
Negatives:
Hard to get or set Entity-implemented fields of an instance.
Attempt 2:
class Entity e where
getLocation :: e -> Vector
getVelocity :: e -> Vector
...
setLocation :: Vector -> e -> e
setVelocity :: Vector -> e -> e
...
data Player = Player {
playerLocation :: Vector,
playerVelocity :: Vector,
...
playerHealth :: Int
}
instance Entity Player where
getLocation = location
getVelocity = velocity
...
setLocation l e = e {location = l}
setVelocity v e = e {playerVelocity = v}
...
move :: (Entity e) => e -> e
move e = (setLocation (getLocation e + getVelocity e) . setAngle (getAngle e + getRotation e)) e
Well it works, but I hope we can all agree that their definitions are now really ugly. The abstract methods which work on any Entity also becomes way ugly. The only good thing is that methods like movePlayer become really easy.
movePlayer :: Player -> Player
movePlayer = move
I don't even need to define movePlayer anymore, since I can just use move.
Positives:
Easy to get or set Entity-implemented fields of an instance.
Negatives:
Hard to create the abstract class.
Even harder to create instances.
Hard abstract methods.
Attempt 3:
Give Entity all fields that any instance needs.
data Entity = Entity {
location :: Vector,
velocity :: Vector,
angle :: Float,
rotation :: Float,
health :: Int,
pickupType :: PickupType
}
This way I don't even need to define instances and I can just use Entity. The only problem is that you have a lot of excess data. This is currently what I use and IMO the best solution for my problem, but I still don't like it.
Positives:
Easy to create the abstract class, even though it isn't really abstract anymore.
No need to define instances.
Easy abstract methods.
Easy to get or set Entity-implemented fields of an instance.
Negatives:
A lot of unused data.
You have to define a lot of nonsense fields every time you create an Entity.
So please help me, I can't find any better methods than these three :(
I would go with your first attempt, for a very simple reason:
It accurately captures the intention of a Player - it's an Entity with additional information.
data Player = Player {
e :: Entity
health :: Int
}
While all functions dealing with may be cumbersome to write at first, you will probably never have to see them again, meaning you provided an abstract enough interface in your code not to access the state of a Player directly.
movePlayer :: Player -> Player
movePlayer p#(e) = p {e = move e}
This function is written once and then ideally you never have to deal with internals again.
Additionally, now you can use type classes as they are intended: you can abstract movePlayer in a separate type class such as Movable:
class Movable m where
move :: m -> m
-- Obviously, you can move entities
instance Movable Entity where
move e = -- stuff
But now it's really easy to move Players too:
instance Movable Player where
move (Player entity health) = Player (move entity) health
-- works, since `Entity` is movable
This aside, your type class approach has a major flaw: What about functions a Player has but an Entity doesn't? In this case you would have Player inherit Entity, like this:
class Entity e => Player e where
-- stuff ...
But since Haskell's type classes are open, anything can become a Player, which is not how it's supposed to work (unless, of course, that is your intention).
I would say that your first attempt is the way to go, for the same reasons as given in #ThreeFx's answer. I'm going to suggest a slightly different alternative though.
Given these types:
data Player = Player {
playerEntity :: Entity,
health :: Int
}
data Pickup = Pickup {
pickupEntity :: Entity,
pickupType :: PickupType
}
Instead of having a separate type class for each action that can be done on an Entity, we can provide generic higher-order functions to make it easier to perform Entity actions on Players and Pickups:
overPlayerEntity :: (Entity -> Entity) -> Player -> Player
overPlayerEntity fn (Player pe h) = Player (fn pe) h
overPickupEntity :: (Entity -> Entity) -> Pickup -> Pickup
overPickupEntity fn (Pickup pe t) = Pickup (fn pe) t
Now, we can have
movePlayer = overPlayerEntity move
movePickup = overPickupEntity move
We can also wrap this up into a type class to make it easier to write generic code as well:
class HasEntity a where
overEntity :: (Entity -> Entity) -> a -> a
instance HasEntity Player where overEntity = overPlayerEntity
instance HasEntity Pickup where overEntity = overPickupEntity
This allows things like:
move' :: HasEntity a => a -> a
move' = overEntity move
which works with both Players and Pickups. This eliminates the need for a specialized version of functions like move and at the same time we only need to write the Entity access boilerplate once.
Incidentally, this over...Entity way of doing things is approaching the "lens" technique mentioned at the end of #duplode's and #Paul Johnson's answers. These are essentially two (very) specialized lenses. If we add in the HasEntity type class it gives us what might be called a "classy lens" (this is sort of the terminology used in the lens library). You don't really need to worry about what the general lens concept means or entails, but this could give you an entry point to learn about lenses in the future.
You could just use a sum (aka "union") type.
data Entity =
Player {
location :: Vector,
-- etc.
health :: Int }
| Pickup {
location :: Vector,
-- etc.
pickupType :: PickupType}
You can factor this out by just having the sum type hold the data that varies.
This has the advantage that you can have a [Entity], which is something you can't do when all the different variations of Entity are different types (unlike OO languages).
Depending on your game model you might also want to separate the location and velocity data from the rest of the player information. Could that data be better held in some kind of spatial data structure like a quadtree? That way you can keep the constant data separate from the stuff that changes with every frame.
One thing you ought to look at are lenses, which exist to solve the problem you describe with lots of getters and setters.
This is more of a long comment than an answer, as the core of what I was going to write is covered well enough by ThreeFx's answer.
Firstly, avoid using OOP jargon, as it will lead to confusion. In your attempt #1, Entity is a data type, not a class, and it is not abstract either. The relationship between Player and Entity in attempt #1 is merely one of composition: a Player has an Entity, and it is not in any way an instance of Entity.
Secondly, record update syntax is quite ugly in Haskell. That doesn't make it complicated, just a little cumbersome. So when you say e.g. "Hard to get or set Entity-implemented fields of an instance", it is not actually hard, just not too pretty. That is not a serious enough concern to determine the design of your data types.
Thirdly, lenses are a way of (among many other things) avoiding the ugliness of the record update syntax. You probably won't want to dive into that right now (wait at least until you have finished your assignment), but I can't resist leaving a link to a highly relevant tutorial for you to read at some point in the future: Program imperatively using Haskell lenses.
I'm attempting to simulate a checkers game using haskell. I am given a 4-tuple named, checkersState, that I would like to manipulate with a few different functions. So far, I have a function, oneMove, that receives input from checkerState and should return a tuple of the modified data:
The Input Tuple:
(
3600,
"",
[
"----------",
"------r---",
"----------",
"----------",
"---r-r----",
"------r---",
"---w---w-w",
"----------",
"----------",
"------w---"
],
(
49
,
43
)
)
So far I have something similar to below defining my function but am unsure how to access the individual members within the tuple checkerState. This method will take a time, array of captured pieces, board, and move to make, and return a time, array of captured pieces, and board. Currently, I would like to modify the time (INT) in the tuple depending on the state of the board:
onemove :: (Int,[Char],[[Char]],(Int,Int)) -> (Int,[Char],[[Char]])
Thanks in advance!
You can use pattern-matching to pull out the elements, do whatever changes need to be made, and pack them back into a tuple. For example, if you wanted to increment the first value, you could:
onemove (a,b,c,d) = (a + 1,b,c,d)
If you find yourself doing this a lot, you might reconsider using a tuple and instead use a data type:
data CheckersState = CheckersState { time :: Int -- field names are just
, steps :: [Char] -- guesses; change them
, board :: [[Char]] -- to something that
, pos :: (Int, Int) -- makes sense
} deriving (Eq, Read, Show)
Then you can update it with a much more convenient syntax:
onemove state = state { time = time state + 1 }
If you want to stick with tuples and you happen to be using lenses, there’s another easy way to update your tuple:
onemove = over _1 (+1)
Or if you’re using lenses and your own data type (with an appropriately-defined accessor like the one provided), you can do something similar:
_time :: Lens' CheckersState Int
_time f state = (\newTime -> state { time = newTime }) <$> f (time state)
onemove = over _time (+1)
So there’s plenty of fancy ways to do it. But the most general way is to use pattern-matching.
As icktoofay is saying, using tuples is a code smell, and records with named components is way better.
Also, using Char (and String) is a code smell. To repair it, define a data type that precisely describes what you expect in a cell of the board, like data Colour = None | Red | Black, but see next item.
And, using Lists is also a code smell. You actually want something like type Board = Data.Map.Map Pos Colour or Data.Map.Map Pos (Maybe Colour') with data Colour' = Red | Black.
Oh, and Int is also a code smell. You could define newtype Row = Row Int ; newtype Col = Col Int ; type Pos = (Row,Col). Possibly deriving Num for the newtypes, but it's not clear, e.g., you don't want to multiply row numbers. Perhaps deriving (Eq,Ord,Enum) is enough, with Enum you get pred and succ.
(Ah - this Pos is using a tuple, thus it`s smelly? Well, no, 2-tuples is allowed, sometimes.)
You use pattern matching to decompose the tuple into variables.
onemove (i, c, board, (x, y)) = <do something> (i, c, board)
However, you should define a separate data structure for the board to make your intention clear. I don't know what the meaning of the first two values. See: http://learnyouahaskell.com/making-our-own-types-and-typeclasses
I can't seem to find any explanation of what lenses are used for in practical examples. This short paragraph from the Hackage page is the closest I've found:
This modules provides a convienient way to access and update the elements of a structure. It is very similar to Data.Accessors, but a bit more generic and has fewer dependencies. I particularly like how cleanly it handles nested structures in state monads.
So, what are they used for? What benefits and disadvantages do they have over other methods? Why are they needed?
They offer a clean abstraction over data updates, and are never really "needed." They just let you reason about a problem in a different way.
In some imperative/"object-oriented" programming languages like C, you have the familiar concept of some collection of values (let's call them "structs") and ways to label each value in the collection (the labels are typically called "fields"). This leads to a definition like this:
typedef struct { /* defining a new struct type */
float x; /* field */
float y; /* field */
} Vec2;
typedef struct {
Vec2 col1; /* nested structs */
Vec2 col2;
} Mat2;
You can then create values of this newly defined type like so:
Vec2 vec = { 2.0f, 3.0f };
/* Reading the components of vec */
float foo = vec.x;
/* Writing to the components of vec */
vec.y = foo;
Mat2 mat = { vec, vec };
/* Changing a nested field in the matrix */
mat.col2.x = 4.0f;
Similarly in Haskell, we have data types:
data Vec2 =
Vec2
{ vecX :: Float
, vecY :: Float
}
data Mat2 =
Mat2
{ matCol1 :: Vec2
, matCol2 :: Vec2
}
This data type is then used like this:
let vec = Vec2 2 3
-- Reading the components of vec
foo = vecX vec
-- Creating a new vector with some component changed.
vec2 = vec { vecY = foo }
mat = Mat2 vec2 vec2
However, in Haskell, there's no easy way of changing nested fields in a data structure. This is because you need to re-create all of the wrapping objects around the value that you are changing, because Haskell values are immutable. If you have a matrix like the above in Haskell, and want to change the upper right cell in the matrix, you have to write this:
mat2 = mat { matCol2 = (matCol2 mat) { vecX = 4 } }
It works, but it looks clumsy. So, what someone came up with, is basically this: If you group two things together: the "getter" of a value (like vecX and matCol2 above) with a corresponding function that, given the data structure that the getter belongs to, can create a new data structure with that value changed, you are able to do a lot of neat stuff. For example:
data Data = Data { member :: Int }
-- The "getter" of the member variable
getMember :: Data -> Int
getMember d = member d
-- The "setter" or more accurately "updater" of the member variable
setMember :: Data -> Int -> Data
setMember d m = d { member = m }
memberLens :: (Data -> Int, Data -> Int -> Data)
memberLens = (getMember, setMember)
There are many ways of implementing lenses; for this text, let's say that a lens is like the above:
type Lens a b = (a -> b, a -> b -> a)
I.e. it is the combination of a getter and a setter for some type a which has a field of type b, so memberLens above would be a Lens Data Int. What does this let us do?
Well, let's first make two simple functions that extract the getters and setters from a lens:
getL :: Lens a b -> a -> b
getL (getter, setter) = getter
setL :: Lens a b -> a -> b -> a
setL (getter, setter) = setter
Now, we can start abstracting over stuff. Let's take the situation above again, that we want to modify a value "two stories deep." We add a data structure with another lens:
data Foo = Foo { subData :: Data }
subDataLens :: Lens Foo Data
subDataLens = (subData, \ f s -> f { subData = s }) -- short lens definition
Now, let's add a function that composes two lenses:
(#) :: Lens a b -> Lens b c -> Lens a c
(#) (getter1, setter1) (getter2, setter2) =
(getter2 . getter1, combinedSetter)
where
combinedSetter a x =
let oldInner = getter1 a
newInner = setter2 oldInner x
in setter1 a newInner
The code is kind of quickly written, but I think it's clear what it does: the getters are simply composed; you get the inner data value, and then you read its field. The setter, when it is supposed to alter some value a with the new inner field value of x, first retrieves the old inner data structure, sets its inner field, and then updates the outer data structure with the new inner data structure.
Now, let's make a function that simply increments the value of a lens:
increment :: Lens a Int -> a -> a
increment l a = setL l a (getL l a + 1)
If we have this code, it becomes clear what it does:
d = Data 3
print $ increment memberLens d -- Prints "Data 4", the inner field is updated.
Now, because we can compose lenses, we can also do this:
f = Foo (Data 5)
print $ increment (subDataLens#memberLens) f
-- Prints "Foo (Data 6)", the innermost field is updated.
What all of the lens packages do is essentially to wrap this concept of lenses - the grouping of a "setter" and a "getter," into a neat package that makes them easy to use. In a particular lens implementation, one would be able to write:
with (Foo (Data 5)) $ do
subDataLens . memberLens $= 7
So, you get very close to the C version of the code; it becomes very easy to modify nested values in a tree of data structures.
Lenses are nothing more than this: an easy way of modifying parts of some data. Because it becomes so much easier to reason about certain concepts because of them, they see a wide use in situations where you have huge sets of data structures that have to interact with one another in various ways.
For the pros and cons of lenses, see a recent question here on SO.
Lenses provide convenient ways to edit data structures, in a uniform, compositional way.
Many programs are built around the following operations:
viewing a component of a (possibly nested) data structure
updating fields of (possibly nested) data structures
Lenses provide language support for viewing and editing structures in a way that ensures your edits are consistent; that edits can be composed easily; and that the same code can be used for viewing parts of a structure, as for updating the parts of the structure.
Lenses thus make it easy to write programs from views onto structures; and from structures back on to views (and editors) for those structures. They clean up a lot of the mess of record accessors and setters.
Pierce et al. popularized lenses, e.g. in their Quotient Lenses paper, and implementations for Haskell are now widely used (e.g. fclabels and data-accessors).
For concrete use cases, consider:
graphical user interfaces, where a user is editing information in a structured way
parsers and pretty printers
compilers
synchronizing updating data structures
databases and schemas
and many other situations where you have a data structure model of the world, and a editable view onto that data.
As an additional note it is often overlooked that lenses implement a very generic notion of "field access and update". Lenses can be written for all kinds of things, including function-like objects. It requires a bit of abstract thinking to appreciate this, so let me show you an example of the power of lenses:
at :: (Eq a) => a -> Lens (a -> b) b
Using at you can actually access and manipulate functions with multiple arguments depending on earlier arguments. Just keep in mind that Lens is a category. This is a very useful idiom for locally adjusting functions or other things.
You can also access data by properties or alternate representations:
polar :: (Floating a, RealFloat a) => Lens (Complex a) (a, a)
mag :: (RealFloat a) => Lens (Complex a) a
You can go further writing lenses to access individual bands of a Fourier-transformed signal and a lot more.
how can i group getX and putX in a class instance ?
the code below is an answer for this post Class set method in Haskell using State-Monad
import Control.Monad.State
data Point = Point { x :: Int, y :: Int } deriving Show
getX :: State Point Int
getX = get >>= return . x
putX :: Int -> State Point ()
putX newVal = do
pt - get
put (pt { x = newVal })
increaseX :: State Point ()
increaseX = do
x - getX
putX (x + 1)
Later I hope I will implement setters and getters for a hierarchy of 2 classes, but for now i just wanna do something like this:
class A a where
putX :: Int -> State Point ()
instance A (State Point) where
putX newVal = do
pt - get
put (pt { x = newVal })
You seem to be conflating multiple concepts here, to the point that I'm not sure exactly what you're aiming to accomplish. A few thoughts on what you might be after:
Field access, i.e., a way to inspect or replace a piece of a larger data structure. This doesn't really lend itself to a type class, because for many combinations of "inner field" and "data structure" there will be more than one accessor possible. Abstractions along these lines are often called "lenses".
Stateful references in some generic fashion. For the most part in a State monad this amounts to combining something like the aforementioned lenses with the standard get and put. In this case you could have a type class for the combination of a particular monad and the accessor data type, but it wouldn't really do that much.
Overloading access to a particular field, so that functions can work on any data type that contains an "x" field. In this case I assume you'd also want "y", as some sort of type class for 2D points. This is entirely separate from the above issues, however.
Perhaps you could clarify your goal?