In my main function for my haskell game, I start by loading each sprite. I decided to make a data type called SpriteCollection which holds all the sprites (typed Picture) so I can access them later by their name.
loadBMP is a Gloss function typed String -> IO Picture. This code works:
main = do
-- Load sprites
playerBmp <- loadBMP "assets/mario.bmp"
goombaBmp <- loadBMP "assets/goomba.bmp"
brickBmp <- loadBMP "assets/brick.bmp"
let sprites = SpriteCollection {
marioSprite = playerBmp,
goombaSprite = goombaBmp
brickSprite = brickBmp
}
playIO (... sprites ...)
So as you can see, as I load more sprites, it feels like I am writing double the code that I should need. Is there a way to get rid of the intermediate variables? For example:
main = do
-- Load sprites
let sprites = SpriteCollection {
marioSprite <- loadBMP "assets/mario.bmp",
goombaSprite <- loadBMP "assets/goomba.bmp",
brickSprite <- loadBMP "assets/brick.bmp"
}
playIO (... sprites ...)
but that does not work.
Applicative is the tool for combining multiple values that are in the same sort of context.
In general,
can be written as
but only if the final call to
fis the only thing that referencesxandy. This approach scales to arbitrarily many arguments. For small numbers of arguments, you can try something from theliftAfamily of functions, such asliftA2 f mx my.