Jump to content

[Haskell] Converter um IO Int para um Int


Recommended Posts

Posted

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.

Posted

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)
Posted

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.

Posted

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.

Posted

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).

Posted

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.

Posted

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...

Posted

Boas!

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

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:

Posted

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.

Posted

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

Posted

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

Posted

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ó... 😕

Posted

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...

Posted

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.

Posted
' 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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.