[Haskell-cafe] using haskell for a project

Sebastian Sylvan sebastian.sylvan at gmail.com
Sat May 2 17:46:01 EDT 2009


On Sat, May 2, 2009 at 6:17 PM, Nicolas Martyanoff <khaelin at gmail.com>wrote:

> Hi,
>
> I don't think I already presented myself; I'm Nicolas, a 23y french
> student, trying to learn and use haskell.
>
> I've been using C for years, for all sort of tasks, and am quite
> comfortable with it. I'm also using it 40h a week in my internship for
> network systems, so I kind of know how to use it.
>
> I discovered Haskell some monthes ago, bought `Real World Haskell',
> quickly read, and enjoyed it.
>
> So now I'd want to use it for a small project of mine, a simple
> multiplayer roguelike based on telnet. I wrote a minimal server in C, and
> it took me a few hours. Now I'm thinking about doing the same in Haskell,
> and I'm in trouble.
>
> I don't really know how to map my ideas in haskell code. For example, a
> character can cast spells, so I'd have something like this in C:
>
>    struct hashtable spells;
>
>    struct character {
>        int n_spells;
>        struct spell **spells;
>    };
>
> I thought I could do something like this in haskell:
>
>    spells = Data.Map.Map Int Spell
>
>    data Character = Character { charSpells :: [Int] }
>
> But now I don't know how to dynamically add new spells (new spells can be
> created in my gameplay). Since I can't assign a new value to the `spells'
> variable (Data.Map.insert returns a new map), I just don't know where to
> go.


I'm not sure I understand how your C version and Haskell version are
similar?
Wouldn't the character just have a list of Spells (since this is what the C
version seems to do)? That global spells variable should probably be put in
some sort of "game state" data type that encapsulates the game world.

Then consider writing updates as a function that takes the old value, and
produces a new value. Indeed, consider letting the following function be
your main "update" for the game state.

gameTick :: Time -> PlayerInput -> GameState -> GameState

That function would update all parts of your game state, and if you want to
change some property of a character, you simply compute a new character from
the old one with the field you want to change updated. Because values are
immutable, any data you don't touch will just refer to the old stuff so it's
actually quite efficient.

You main loop could then be something like:

gameLoop oldTime gameState = do
  time <- getTime
  let dt = time - oldTime
  input <- processInput gameState
  gsNew <- gameTick dt input gameState
  renderGame gsNew
  gameLoop time gsNew


>
> I just wanted a 2d array to store a zone, for example, dead simple in C,
> but this kind of link
> http://greenokapi.net/blog/2009/03/10/rough-grids-in-haskell make me
> shiver.


Try a list of lists, or better yet just an Array. Make sure you update the
grid "in bulk" though, as modifying just a single element at a time is slow
with immutable arrays.


> Point is, I'd like to use haskell, but I don't know how, it seems totally
> alien.
>
> How did you manage to change the way you map ideas to code, from
> imperative to pure functional ?


Massive brain-rewiring. Keep at it, don't think in terms of modifying state,
think of it as computing new values from old values. I find that the payoff
of learning to think ,like this is massive, as it's usually much easier to
reason about.

If you really do lots of "state" in a program, consider using a state monad
like someone else already mentioned, but honestly I'd try to stay away from
it and stick to a more "functional" style as far as possible.

-- 
Sebastian Sylvan
+44(0)7857-300802
UIN: 44640862
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20090502/4f82795f/attachment.htm


More information about the Haskell-Cafe mailing list