At 7:17 PM +0200 5/2/09, Nicolas Martyanoff wrote:
Content-Type: multipart/signed; micalg=pgp-sha1;
        protocol="application/pgp-signature"; boundary="ibTvN161/egqYuK8"
Content-Disposition: inline

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 have the same problem for a bout every problem. I love writing pure
functions in haskell, but as soon as I try to write some code involving
states or side effects, I can't write a line.

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.

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 ?

Thank you.

Regards,

--
Nicolas Martyanoff
   http://codemore.org
   khaelin@gmail.com

Nicolas,

First, bienvenue à Haskell !  Learning it will stretch your mind; it may be rocky at times, but it will be rewarding.

You've quickly come upon a key difference between imperative and functional programming.  State management in Haskell is more explicit, which is a double-edged sword.  It requires greater discipline and mechanism, but provides greater control and security.

In your example program you could manage your state with a State monad.  Assuming you'll want to be able to do I/O, you'll probably want to combine State with IO.  For starters, something like:

> import Control.Monad.State
> import qualified Data.Map as M
>
> data Spell = ...
> data Character = Character { charName :: String, charSpells :: [Spell], ... }
> data MyState = MyState { characters :: M.Map String Character, ... }
> initialState = MyState { characters = M.empty, ... }
>
> type MyMonad = StateT MyState IO
>
> addSpellForCharacter :: String -> Spell -> MyMonad ()
> addSpellForCharacter name spell = do
>     state <- get
>     let chars = characters state
>     case M.lookup name chars of
>         Just char -> let char' = char { charSpells = spell : charSpells char }
>                          state' = state { characters = M.insert name char' chars }
>                      in put state'
>         Nothing   -> ...  -- leave these issues for another time
>
> main = do
>     ...
>     finalState <- execStateT game initialState
>     ...
>
> game :: MyMonad ()
> game = do
>     ...
>     addSpellForCharacter ...
>     liftIO $ putStrLn "Added spell ..."
>     ...

Dean