Hacker News new | past | comments | ask | show | jobs | submit login

So how do you keep state like health points in a functional language? :)



One way you could do it is by using mutable state. Impure languages, such as Scheme or Ocaml, let you use mutable like normal imperative languages do and in Haskell you can use mutable references inside some special monads (and you even ave more than one kind of mutalbe reference, depending on what monad you are on: IORef, STRef, etc)

The other way is to not use state. If you squint a bit, you can see that if you explicitly encode your "state" as function arguments you can kind of update it by calling the function recursively:

   go 0 acc = acc
   go n acc = go (n-1) (n * acc)

   fact n = go n 1
In the previous example, the code I wrote does exactly the same thing as the usual imperative loop might have done, but the accumulator is a parameter on the helper function instead of being a mutable variable.

In general, if you are OK with this kind of non-destructive updates that I used here, you can encode all your state as extra parameters that you thread around your functions. You can do this by hand in most cases but in some situations the state is very pervasive and correctly threading it around can be complex and error prone. In that case, you can look into use things like the State monad (not to be confused with the ST monad!) to do that implicitly pass that parameter around for you.


But for a game your state needs to update at specific time intervals, otherwise you walk too slow or too fast. How can that ever be purely expressed?

Personally, I would love to see more functional possibilities in imperative languages, but have regular imperative possibilities as well. E.g. running the game and keeping state seems pretty suitable for imperative code. But doing certain updates or calculations could be expressed better with functional code.


> But for a game your state needs to update at specific time intervals, otherwise you walk too slow or too fast. How can that ever be purely expressed?

In this case you want ot have a system that reacts to an event that fires on a regular interval (as well as other sorts of input events). If you search for Functional Rdeactive Programming you will find some example libraries out there that try to do this in a pure manner (although I would personally have to say that this is all still a bit on the experimental side of things).

That said, Haskell still lets you do things the imperative way if you want! All you need to do is put the impure code in the IO monad, where it belongs.

You are only forced to be purely functional if you want to or if whoever is calling you must be a pure function. So basically, the idea is that your `main` function is impure code in the IO monad and it can call either more impure code or pure "helper" functions. Increasing the percentage of your code that is pure is a nice thing but its not mandatory.


>How can that ever be purely expressed?

A loop is a recursive function. State is the arguments to the function. You pass an updated state to the next iteration of the loop. Haskell provides nice abstractions to make this seamless.


"Sufficiently advanced trolling is indistinguishable from ignorance." I'm leaning slightly towards troll due to the smiley face. But I find myself forced to reply anyway, because such a good tutorial came out recently that covers doing exactly what this question asked about. http://www.haskellforall.com/2013/05/program-imperatively-us...


No, it was not a troll. The thing is, I sort of know the answer, but it never fully reaches my inner understanding, and at the same time I'm interested in it, so I just asked the core issue of what I'm always wondering in the most simple form... Maybe I should just actually try it with a functional language, but never get around to do it.


Health points isn't a state, it's a piece of data that exists at a given time. If you have time, go on YouTube and watch some talks Rich Hickey gives about state, he breaks it down far more eloquently than I can.


From what I hear (I don't use functional languages, so I don't know for sure), functional languages minimize state, but don't erase it entirely.


You can do something like:

  gameLoop curState = do
    inputs <- getInputs
    let newState = gameIteration curState inputs
    drawState newState
    gameLoop newState





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: