1

I am creating a simple terminal game with Haskell and got stuck big time implementing health system. Ended up with idea to save changing health points to a text file, in this way keeping it as a "variable".

My code:

readHealth = do 
    theFile <- openFile "health.txt" ReadMode
    healthPoints <- hGetContents theFile
    return healthPoints 

Problem here is that I can not access "healthPoints" outside of this readHealth thing... Any suggestions?

2
  • 2
    Don't use global variables. This is a bit similar to "global state". IO means you define a recipe to obtain the value, it is not the value itself. Commented May 11, 2020 at 19:42
  • 2
    Just pass it as a variable, for example GameContext that contains data about the state of the game. Commented May 11, 2020 at 19:45

1 Answer 1

2

This is not an appropriate solution to your problem. It is impossible* to extract data from the IO monad, because that's not it's purpose. You should instead look into using the State monad family (or it's close cousins StateT), which lets you carry a mutable value along with you through the program, like so:

data Game = Game { health :: Int, ... }
type GameState = State Game

Then to read your value from the main thread, you use:

gameloop :: GameState ()
gameloop = do
    currentHealth <- gets health
    pure ()

To update the health, you need a short function:

updateHealth :: Int -> Game -> Game
updateHealth newHealth game = game { health = newHealth }

Then you can set health to 10 with:

gameloop :: GameState ()
gameloop = do
    modify $ updateHealth 10
    pure ()

Usage examples:

> evalState (gets health) (Game { health = 10 })
10

> evalState (modify (updateHealth 20) >> gets health) (Game { health = 10 })
20

* It is actually possible to extract values from IO using unsafePerformIO, but as the name suggests, it is unsafe to do so unless you really know what you're doing.

Sign up to request clarification or add additional context in comments.

3 Comments

You could also use Lenses, but I'll leave that for someone else to explain since I barely understand them myself. I think it's valuable to become familiar with basic States before diving into Lenses anyways.
Sorry again, have a missunderstanding on "currentHealth <- gets health" this part. If I use this block it just throws bunch of errors.
@HumanCode you should ask a new question and provide the exact code you're using. This code compiles, so it's probably just not interacting well with something else.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.