[Haskell-cafe] using haskell for a project

Bulat Ziganshin bulat.ziganshin at gmail.com
Sun May 3 14:32:18 EDT 2009


Hello Nicolas,

Saturday, May 2, 2009, 9:17:55 PM, you wrote:

> 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.

well, i've written mid-size program that combines pure haskell,
imperative haskell and c++ and that's my vision:

in C, you don't have the barrier between pure and imperative worlds
and as result you don't got habit to distinguish them. haskell forces
you to separate pure and imperative code: pure code is much simpler to
write but it cannot call imperative one (i.e. function can't call
procedures) so you should understand the difference and carefully
make your choice

you are *forced* to use imperative code when it responds to some
external events - user input, network input, so on. so when your spell
list mutates as a result of external events, you should do something
imperatively. although it may be as easy as tail-recursively calling
itself with purely modified value:

mainCycle spells = do
  x <- userInput
  case x of
    AddSpell -> mainCycle (newSpell:spells)
    ....

further improving this idea, you may develop data structire contating
whole state info:

data GameState = GameState {spells: [Spell],
                            .....}

and update appropriate parts of GameState on tail-recursive calls:

mainCycle gameState = do
  x <- userInput
  case x of
    AddSpell -> mainCycle (gameState {spells = newSpell:spells gameState})
    ....

as you see, this approach allows you to live in imperative world but
use only pure computations to update state


but once your program will become larger, you may find that this
approach needs too much typing. in that case, you can program using
IORefs, MVars and other types of C-like global vars. or, you may use
them semi-globally - i.e. create this vars in outside procedure and
then pass to all interested routines:

main = do vspells <- newIORef []
          let stateVars = StateVars {spells=vspells, ...}
          mainCycle stateVars

you may even use implicit parameters to hide passing details from
program code but i don't have experience of using them


-- 
Best regards,
 Bulat                            mailto:Bulat.Ziganshin at gmail.com



More information about the Haskell-Cafe mailing list