Talles Silva
Talles Silva

Reputation: 15

How to use the setElem in Haskell to update the Matrix

I'm trying to use the function setElem in Haskell to update the Matrix, but seems the new value does not stay in the matrix. Is there a way to use this function to go around this problem?

I'm new with Haskell and what I need is to set a new value in the matrix and then show the matrix updated.

setElem :: a -> (Int, Int) -> Matrix a -> Matrix a

My code:

import Data.Matrix
import System.Random
import System.IO 
import Data.Array



table_game = matrix 20 20 $ \(i,j)-> "#"


inputCoordenadas = do       
            putStrLn "Digite -1 -1 para encerrar: "
            putStrLn "Digite a coordenada X: "
            coord_x <- getLine
            putStrLn "Digite a coordenada Y: "
            coord_y <- getLine
            let x = (read coord_x :: Int)
            let y = (read coord_y :: Int)
            if(coord_x == "-1"  && coord_y=="-1") then do 
                putStrLn ("Encerrando o jogo...")
                return ()
            else do 
                print $ setElem "X" (2,2) table_game
                print table_game
                inputCoordenadas


main = do   
    putStrLn "Iniciar jogo|1 - Encerrar jogo|0: "
    buffer <- getLine
    let n = (read buffer :: Int)    


if n==0 then do 
        putStrLn "Encerrando o jogo"
        return ()
 else do
    print table_game
    inputCoordenadas

Upvotes: 1

Views: 213

Answers (2)

Redu
Redu

Reputation: 26161

Haskell uses pure functions. Pure functions can not modify anything out of their context and prevent side effects. What you are trying is a sin in Haskell. Setting a global variable and trying to mutate it is a no no.

You are basically expected to structure your code such that the inputCoordenadas function takes a table-game (tg in my code below), prints it, modifies it and returns a new table-game. With minimal change your code should be like

import Data.Matrix
import System.Random
import System.IO 
import Data.Array

inputCoordenadas tg = do
    print tg
    putStrLn "Digite -1 -1 para encerrar: "
    putStrLn "Digite a coordenada X: "
    coord_x <- getLine
    putStrLn "Digite a coordenada Y: "
    coord_y <- getLine
    let x = (read coord_x :: Int)
    let y = (read coord_y :: Int)
    if(coord_x == "-1"  && coord_y=="-1") then putStrLn "Encerrando o jogo..."
                                          else inputCoordenadas $ setElem "X" (x,y) tg

main = do
    putStrLn "Iniciar jogo|1 - Encerrar jogo|0: "
    buffer <- getLine
    let n = (read buffer :: Int)
    if n==0 then  putStrLn "Encerrando o jogo"
            else  inputCoordenadas $ matrix n n (\(i,j) -> "#")

Upvotes: 1

luqui
luqui

Reputation: 60463

Haskell does not have mutable variables. The simplest (least abstract) way to do this is to add a parameter to your function:

inputCoordinadas tab = do
    ....
    let newTab = setElem "X" (x,y) tab
    inputCoordinadas newTab

So each time the function is called, it is called with the "current" table. When it calls itself, it passes an updated table.

There are fancier ways to do this but this solution is also fine and relatively common even among those who know the fancy ways.

Upvotes: 1

Related Questions