[Resolvido] Haskell - Dúvida ao compilar

MPalhas

Power Member
tenho um programa em Haskell que estou a fazer para o trabalho de Programação Funcional, que consiste num jogo parecido com o 4 em linha.

estou a programar no Ubuntu, e daquilo que tenho feito até agora, corre tudo sem problemas no GHCi.
mas quando tento compilar com o GHC o que acontece é que sempre que o programa tem que escrever uma string e depois pedir um valor, o que ele faz é o contrário, ou seja primeiro pede o valor e só depois escreve a string que deveria ter escrito antes

o comando que uso para compilar é: ghc --make Main.hs
muito provavelmente o problema está aqui, já que não encontrei nenhuma informação sobre qual o comando correcto, e após algumas tentativas este foi o primeiro que não deu erro ao compilar


outra dúvida que queria aproveitar para esclarecer era sobre números aleatórios. já estive a procurar no Hoogle mas não não consegui perceber quais as funções que tenho que chamar e com que parametros (além de que fazer "import Random" parece não funcionar)
 
Última edição:
Como é que estás a fazer esse processamento do I/O? Isso está dentro de um bloco do {...} (supondo que isso está feito com Monad IO)?
Para gerar os números aleatórios podes usar as funções randomR e getStdRandom em conjunto:
Código:
num = getStdRandom(randomR (1,6))
Isto gera um monad IO com um integer lá dentro, que está no intervalo [1,6].
Tenta também fazer "import System.Random".
 
para o IO criei uma função que me serve para a maioria dos casos que preciso. ela escreve a string com a pergunta, le o valor, verifica se ele está no intervalo permitido e se pode ser convertido para inteiro. caso seja devolve esse valor, senão volta a pedir

Código:
readOption :: String -> Int -> Int -> IO Int
readOption question min max = do
                        putStr question 
                        op <- getChar
                        getLine
                        let opInt = (read [op])::Int
                        if (isValidInt [op] && opInt>=min && (opInt <=max || max<0)) then return (opInt)
                                             else do
                                                    putStrLn "Invalid value!"
                                                    readOption question min max


----------------------------------------
----------------------------------------
-- checks a string to see if it can be converted to Int.
-- note, an empty string is not considered a correct value
isValidInt :: String -> Bool
isValidInt [] = False
isValidInt (x:xs) = (ord x >= ord '0') && (ord x <= ord '9') &&
                    (if (xs==[]) then True
                                 else (isValidInt xs))
já agora aquele getLine que eu pus a seguir ao getChar é para apanhar o ENTER que não é recebido pelo getChar. caso contrário iria interferir com o getChar/getLine que viesse a seguir. não sei se é a maneira mais correcta de fazer isso, mas funciona (também já verifiquei e não é isso que está a causar o problema)


para ajudar a perceber o que acontece, isto é o aspecto do programa correndo pelo GHCi


e isto é o que acontece ao correr exactamente a mesma versão, mas compilada pelo GHC (com o comando referido no outro post)
 
já agora aquele getLine que eu pus a seguir ao getChar é para apanhar o ENTER que não é recebido pelo getChar. caso contrário iria interferir com o getChar/getLine que viesse a seguir. não sei se é a maneira mais correcta de fazer isso, mas funciona (também já verifiquei e não é isso que está a causar o problema)

Relativamente a esta parte, não precisas desse artifício. Basta leres o valor com getLine em vez de getChar e depois tratas op como uma String:

Código:
readOption question min max = do
                        putStr question 
                        op <- getLine
                        let opInt = (read op)::Int
                        if (isValidInt op && opInt>=min && (opInt <=max || max<0)) then return (opInt)

Quanto ao problema que te dá, não sei qual a causa, mas de certeza que não é do comando de compilação porque esse está correcto. Eu como costumo correr sempre o programa a partir do GHCi, não tenho desses problemas.
 
Quanto ao problema que te dá, não sei qual a causa, mas de certeza que não é do comando de compilação porque esse está correcto. Eu como costumo correr sempre o programa a partir do GHCi, não tenho desses problemas.

só para ficar esclarecido... falei ontem com a prof e ela disse-me para usar o seguinte comando no inicio da função main:

hSetBuffering stdout NoBuffering
 
É feito com o uso do monad IO, que é a forma que Haskell fornece para input/output. Podes usar a notação "do" para o efeito. Ficaria algo do género:

Código:
menu :: IO()
menu = do { putStrLn "Menu principal\n";
        putStrLn "1 - Comecar a jogar";
        putStrLn "2 - Carregar jogo";
        putStrLn "3 - Sair";
        opcao <- getLine;
        case opcao of "1" -> putStrLn "Opcao 1 escolhida";
              "2" -> putStrLn "Opcao 2 escolhida";
              "3" -> putStrLn "Leaving..."
              }
 
yah yah.. ja reparei nisso! ;)
obrigado

e em relação ao tabuleiro do jogo? para o transformar num aspecto gráfico semelhante recorro ao mesmo método?


edit: outra questão, ao correr o programa este não abre automaticamente o menu principal... sendo que tenho que introduzir a função "menu" para que este apareça. COmo faço para que ele apareça automaticamente?
 
Última edição:
e em relação ao tabuleiro do jogo? para o transformar num aspecto gráfico semelhante recorro ao mesmo método?

Para isso, precisas de definir o tipo do tabuleiro como uma instância da classe Show e, nessa definição é que dizes como mostras o tabuleiro. A partir daí, sempre que numa função, devolveres o tipo do tabuleiro, ele aparecerá desenhado tal como tu o definiste na instância de Show.

edit: outra questão, ao correr o programa este não abre automaticamente o menu principal... sendo que tenho que introduzir a função "menu" para que este apareça. COmo faço para que ele apareça automaticamente?

Experimenta ver aqui no 5.6.4.
 
Para isso, precisas de definir o tipo do tabuleiro como uma instância da classe Show e, nessa definição é que dizes como mostras o tabuleiro. A partir daí, sempre que numa função, devolveres o tipo do tabuleiro, ele aparecerá desenhado tal como tu o definiste na instância de Show.

Exacto, a dificuldade está mesmo em definir o tipo do tabuleiro como uma instância da classe Show... pois de instâncias e classes não percebo praticamente nada!

:S

Cumps
 
Back
Topo