• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Nazgulled

[Haskell] Converter um IO Int para um Int

21 mensagens neste tópico

Estou aqui com um poroblema gravissimo que me esta a impedir a continução deste trabalho para entregar até dia 2 e ainda vou no inicio...

Num determinado exercicio tinhamos de gerar numeros aleatorios e para isso, com uma pesquisa na net, desenvolvi o seguinte código:

-- Gera um número aleatório compreendido entre o par (x, y)
geraNumeroAleatorio :: (Int, Int) -> IO Int
geraNumeroAleatorio (x, y) =
do
	r <- getStdRandom $ randomR (x, y)
	return r

O problema esta em usar o valor devolvido por esta função para outros fins onde apenas tenho de usar Int e não IO Int. Por exemplo, criar uma lista de inteiros com vários numeros aleatorios e depois somar todos esses valores excluindo o mais baixo. Tudo isto era muito fácil se fosse uma lista de Int, numa lista de IO Int não consigo, mas eu preferia saber (se possível) como converter o valor devolvido pela função geraNumeroAleatorio do tipo IO Int para apenas Int.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

não sei se isso será possível... penso que só podes usar funções do tipo IO dentro de outras funções do tipo IO.

deixo-te aqui uma função semelhante à que tens mas que te calcula uma lista de n números aleatórios, talvez ajude...

geraN::Int->(Int,Int)->IO [int]
geraN 0 _    =return []
geraN n (x,y)=do l<-geraN (n-1) (x,y)
                 new<-randomRIO (x,y)
                 return (new:l)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Que cena, se isso não dá pa fazer, cheira-me que nem um 1/4 do trabalho vou fazer...

Porque tipo, tens essa lista de IO [int], imagina, com 4 valores: [2, 3, 4, 5]. Agora, o objectivo é, usar essa lista, remover o 2 (número mais baixo) e somar os restantes, o resultado seria 12. Como faço eu isso?

Ou seja, nesta situações, de usar sempre IO Int, não vou puder usar a função sum, vou ter de criar a minha função sumIO, certo? Isto vai acontecer o mesmo para todas as outras funções que eu pretenda usar que já estejam definidas no haskell, não vou puder usar porque não funcionam com IO Int.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

podes fazer tudo o que fazia se não fosse com IO, só dá um pouco mais de trabalho...

f::IO Int
f=do l<-geraN 4 (1,10)
     let l1=removeMenor l
     let soma=sum l1
     return soma

esta função gera 4 números entre 1 e 10 aleatoriamente, remove o menor (através da função não monádica removaMenor, que terás de definir), soma os restantes valores e devolve essa soma.

o operador '<-' permite-te ir buscar o resultado de uma função monádica.

o operador 'let ... =' é usado com as não monádicas.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ok, acho que já tou a entrar na cena mas continuo com algumas questões:

1)

Qual a diferença entre eu usar r <- getStdRandom $ randomR (x, y) e new<-randomRIO (x,y)? O caso azul é o que tu me disseste, o a vermelho foi o que eu vi na documentação oficial do Haskell. Qual a diferença e qual o modo recomendado?

2)

Imagine-se o seguinte código:

type ABC = IO (Int, Int, Int)

geraABC :: ABC
geraABC =
do a <- 4
   b <- 2
   c <- 5
   return (a, b, c)

mostraABC :: ABC -> IO()
mostraABC (x, y, z) =
do putStrLn "A: "
   putStrLn (show x)
   putStrLn "B: "
   putStrLn (show y)
   putStrLn "C: "
   putStrLn (show z) 

O objectivo seria compilar correctamente, carregar o ficheiro e fazer o seguinte:

abc <- geraABC

mostraABC abc

e apresentar os resultados no ecrã, mas isto não funciona porque dá o seguinte erro:

Couldn't match `IO (Int, Int, Int)' against `(a, b, c)'

      Expected type: IO (Int, Int, Int)

      Inferred type: (a, b, c)

    When checking the pattern: (x, y, z)

    In the definition of `mostraABC':

        mostraABC (x, y, z)

                    = do

                        putStrLn "A: "

                        putStrLn (show x)

                        putStrLn "B: "

                        putStrLn (show y)

                        putStrLn "C: "

                        putStrLn (show z)

Tentei substituir o type inicial por:

data ABC = IO (Int, Int, Int) | (Int, Int, Int)

Mas dá erro a dizer que não é válido. O que me está escapar para ter este pequeno código a funcionar? (Claro que o verdadeiro exercicio não é este, isto é só um exemplo pequeno para ser mais fácil ajudarem-me).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

relativamente à primeira questão, eu fui à documentação do GHC e encontrei uma função que fazia o que era preciso (gerar números aleatórios) e usei essa função. a modo recomendado é aquele que tu entenderes melhor (ainda não entendi bem a tua solução, em principio e só ver a documentação que está no site, mas acho a minha solução mais simples).

quanto à questão dois, (x,y,z) é uma coisa do tipo (a,b,c) e não IO (a,b,c).

aliás, quando fizeres 'abc<-geraABC' vais ficar com uma variável do tipo (a,b,c). o efeito do operador '<-' é extrair o resultado de uma monad.

podes fazer da seguinte forma:

mostra::IO ()
mostra=
  do (x,y,z)<-geraABC
     putStrLn "A: "
     putStrLn (show x)
     ...

deve resolver o problema.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Isso não vai resolver bem o meu problema porque tipo: Na minha função geraABC, eu tenho valores fixos, mas era só um exemplo, estes valores irão ser aleatorios, logo eu quero puder fazer algo do genero:

a <- geraABC
b <- geraABC
c <- geraABC
(...)

e depois chamo a função que mostra os valores do a, b ou c, conforme me apetecer, não quero gerar estes valores quando for chamar a função que irá mostrar os valores, logo tenho de passar como parametro na função "mostra" algo do tipo ABC. Ai é que esta o problema... por isso é que tentei a cena do Data, ter dois tipos de dados, mas não parece funcionar...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Boas!

Bem...Parece-me que também estás a fazer o trabalho de P.F. :biggrin:

Afinal sempre conseguiste transformar numa lista de inteiros?

A funçao que o Rui Carlos fez que dá uma lista com n ºs aleatorios já chega para fazer os atributos do agente. Tipo, basta gerares uma lista com 4 números a variar entre 3 e 18 (o minimo e maximo de qualquer atributo)

Mas gostava mesmo é de saber transformar numa lista de Inteiros, para depois poder usar os atributos na formula dos modificadores... :dontgetit:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

sim, já resolvi os problemas todos que tinham criado neste tópico...

A solução para o problema que mostrei no meio do topico pode passar pelo seguinte, porque eu tava a fazer uma confusão tremenda:

type ABC = (Int, Int, Int)

geraABC :: IO ABC
geraABC =
do a <- 4
   b <- 2
   c <- 5
   return (a, b, c)

mostraABC :: ABC -> IO()
mostraABC (x, y, z) =
do putStrLn "A: "
   putStrLn (show x)
   putStrLn "B: "
   putStrLn (show y)
   putStrLn "C: "
   putStrLn (show z) 

Compara os 2 e vê as diferenças, esta apenas nos IOs, não sei se isto te ajuda ou não porque não percebi bem a tua dúvida.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem, a minha dúvida é a seguinte. Nós temos lá a formula de modificação [(X-10)/2] certo? Preciso que os valores gerados anteriormente sejam Int, não?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

pessoal tb estou a fazer esse trabalho e ja terminei... so falta o relatorio em latex... vejam se isto ajuda:

d6 = do getStdRandom (randomR (1,6))

geraCaract = do a <- d6;
                b <- d6;
                c <- d6;
                d <- d6;
                return (sum (tail (sort [a,b,c,d])))

ja agora... como passo esta ultima funcao tipo... sem parentises e com pontos?

Abraço, Pires

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
' timestamp='1167351404' post='73138']

ja agora... como passo esta ultima funcao tipo... sem parentises e com pontos?

Abraço, Pires

sum.tail.sort$[a,b,c,d]

penso que isto deve funcionar...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

obrigado amigo Rui Carlos... nao deu mas foi quase  ;) dp consegui chegar la:

return $ (sum.tail.sort) [a,b,c,d]

Abraço, Pires

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Boas pessoal. Estou a ficar lixado... Acho que só me falta mesmo isto para conseguir fazer o resto do trabalho. Como é que conseguiram fazer, por exemplo a tarefa 6? A função recebe Int, mas os valores gerados aleatóriamente não sao Int. A função que o Pires fez ligeiramente modificada:

d6 :: Int -> Int -> IO Int
d6 x y =  randomRIO (x,y)

geraCaract = do          
               a <- d6;
               b <- d6;
               c <- d6;
               d <- d6;
               return (a,b,c,d)

Isto não devia de funcionar? Dar Inteiros? A mim dá-me este erro:

*** Binding             : geraCaract

*** Outstanding context : Monad ((->) Int)

Espero que tenham percebido a dúvida.. Qualquer ajuda é bem-vinda...Abraço

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

o erro está na chamada da função 'd6' (na função 'geraCaract'), que devia estar a receber 2 inteiros.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

ok..obrigado. Só que agora quero usar os inteiros gerados aqui:

modifiers :: Agente -> Modificador
modifiers (a,b,c,d,_) = (truncate(((fromIntegral a)-10)/2),
                        truncate(((fromIntegral b)-10)/2),
                        truncate(((fromIntegral c)-10)/2),
                        truncate(((fromIntegral d)-10)/2)
                       )

*** Term : geraCaract

*** Type : IO (Int,Int,Int,Int)

*** Does not match : (Int,Int,Int,Int,Int)

Ele gera IO (Int...) e não Int só... :confused:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Meus amigos vou vos dar a conhecer uma função que "transforma" um IO a num a, mas que na cadeira em que eu descobri isto (Métodos de Programação 1 do 2º ano) dizia para não utilizar isto, por razões que agora não vou dizer...

Mas o que é facto, é que dá jeito às vezes... lol

Façam  import System.IO.Unsafe

E a dita função é unsafePerformIO, que é do tipo:

unsafePerformIO :: IO a -> a

Mas digo-vos que pode-se escrever os programas em haskell sem usar isto. Por acaso usei uma vez num caso em que não consegui dar-lhe a volta, mas o vosso trabalho de PF (o rpg) não precisa disto...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

este tópico ficou assim um bocado confuso... só não percebo como é que ainda não solucionaram esse problema, a resposta está algures por aqui, eu já consegui resolver a minha dúvida com a ajuda do Rui Carlos. foi pelo messenger, ms de qq forma, tem neste tópico o exemplo que eu tava a ter problemas e o mesmo exemplo solucionado, portanto...

a não ser que a vossa dúvida seja diferente.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu resolvi o meu problema, já acabei o trabalho... Mas só usando o unsafePerformIO é que consegui o que pretendia.

Abraço

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
' timestamp='1167766676' post='74065']

Eu resolvi o meu problema, já acabei o trabalho... Mas só usando o unsafePerformIO é que consegui o que pretendia.

Abraço

acho que os profs não vão achar muita piada à utilização dessa função...

EDIT:

isso está mesmo a funcionar?

neste código

module Teste where

import System.IO.Unsafe
import System.Random

f=do res <- randomRIO (1,10)
     return res

g=unsafePerformIO f

ele só executa a função randomRIO uma vez!!!

ou seja, a função g que devia dar valores aleatórios, gera sempre o mesmo valor em cada execução do ghci!

*Teste> g

1

*Teste> g

1

*Teste> g

1

*Teste> g

1

*Teste> g

1

*Teste> g

1

*Teste> g

1

*Teste> g

1

*Teste> f

10

*Teste> f

7

*Teste> f

9

*Teste> f

7

*Teste> f

9

*Teste> f

4

aconselho a leitura da documetação do GHC (ou do interpretador/compilador que estiverem a usar) para não terem surpresas: http://www.haskell.org/ghc/docs/latest/html/libraries/base/System-IO-Unsafe.html#v%3AunsafePerformIO

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Nós precisavamos de um "agente" com valores que fossem gerados aleatoriamente. Uma vez que o agente não muda até ao fim da aventura, pudemos usar o unsafePerformIO.

Fiz do seguinte modo

type Agente = (Int,Int,Int,Int,Int)

agente :: Agente
agente = (forca,destreza,inteligencia,carisma,500)

d318 :: IO Int
d318 =  randomRIO (3,18)

forca :: Int
forca = unsafePerformIO d318

destreza :: Int
destreza = unsafePerformIO d318

inteligencia :: Int
inteligencia = unsafePerformIO d318

carisma :: Int
carisma = unsafePerformIO d318

Pode não ser a maneira correcta, mas foi a única em que consegui o que pretendia: 4 Int!  :-[

Abraço

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora