[Haskell] Hoe IO Int converteren naar Int *

Pagina: 1
Acties:

  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
Ik kom er niet uit. Misschien is het heel makkelijk, maar google geeft geen duidelijke oplossingen en hier is ook niet te vinden. Dit is de code waar ik niet uit kom:

{--------------------------------------------------
Randomfunctie
---------------------------------------------------}


rollDice :: Int -> Int
rollDice s = do d <- getStdRandom (randomR (1,s));
return d;

Nu doet hij het zowiezo niet, want Int -> Int conflicteerd met Int -> IO Int die Haskell voor die random nodig heeft. Hoe maak ik dus van de IO Int ( die random geeft) een gewone Int??? Ik wil namelijk randomgetallen hebben om in mijn programma te gebruiken en dat lukt me niet met de IO Int die er nu uitkomt.

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Wel, niet ;)
Je werkt immers met een lazy taal dus je weet niet waarneer wat uitgevoerd gaat worden. Je zult dus aan de slag moeten met do en <- (zoals je al doet, wat feitelijk suiker is voor <<=). Voor jouw probleem zou een gebruik van d op je functie genoeg zijn, aangezien de functie pas een Monad maakt met return :)

Zoek eens op monatische IO op google of speur rond in de artikelen op Haskell.org

; is niet nodig in haskell hoor :)

  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
ok dan moet ik daar maar eens even in gaan graven. (Had ik eigenlijk al gedaan :) )

Alleen begrijp ik niet wat hier fout gaat:
Haskell:
1
2
3
4
5
6
7
maakrnd :: Int -> Int -> [Int] -> [IO Int]
maakrnd x 0 xs = do {return rollDice x}
maakrnd x y xs = do {if geenelem (rollDice x) xs 
                then return (maakrnd x (y-1) ((rollDice x):xs)
                else do
                return  (maakrnd x y xs)
                }


Hij zegt unexpected keyword "else" . Maar ik kan die toch gewoon binnen een do gebruiken?
Of moet het een | zijn? Maar die | kan je volgens mij niet gebruiken in een do.

Ik weet dat het hier geen helpdesk is, maar ik heb met het ongeluk gezocht en ik heb gewoon een voorbeeldje nodig. Dan kan ik tenminste weer verder met mijn genetisch algoritme.

[ Voor 4% gewijzigd door Glimi op 20-06-2003 09:05 ]


  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 10-08 15:15
Heb je geen probleem met de layout regels van haskell? Staan de if, then en de else wel netjes onder elkaar?
N.B. zolang je if-then-else maar het juiste type opleveren dan kan je deze gewoon in een do gebruiken.

[ Voor 67% gewijzigd door Infinitive op 20-06-2003 02:20 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Even je indenting gefixed met [ code ] [/] tags, en dan kunnen we zien dat je if then else niet netjes volgens de layoutrule staat :)

BTW rollDice x zal toch geen [IO Int] , maar een IO Int opleveren of zie ik dat nou verkeerd?

  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
ok bedankt.

rollDice levert wel een IO Int op maar maakrnd maakt daar een [IO Int] van. (dat is tenminste de bedoeling. Hij pakt een random getal van rollDice, kijkt of deze al in de lijst zit. Zo ja, dan gaat hij weer verder en zo nee dan zet hij hem in de lijst. Zo krijg ik een lijst met random getallen die allemaal uniek zijn.

Nu uren :) debuggen bleek er een haakje teveel te staan....*zucht*
Waarom is het zo moeilijk om een lijst met random 1en en 0en te maken?

BTW. Kun je IO Ints via == vergelijken? Ja toch?

[ Voor 23% gewijzigd door Appesteijn op 20-06-2003 10:58 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Appesteijn schreef op 20 juni 2003 @ 10:36:
Nu uren :) debuggen bleek er een haakje teveel te staan....*zucht*
Gebruik een degelijke editor! Met een goede editor had je deze fout al tijdens het intypen van de code ontdekt.
Waarom is het zo moeilijk om een lijst met random 1en en 0en te maken?
BTW. Kun je IO Ints via == vergelijken? Ja toch?
Volgens mij wil je hoe dan ook van een IO Int naar een Int gaan, voordat je er iets mee kunt doen. Nu ken ik Haskell verder niet echt, maar ik weet wel dat Haskell gebruik maakt van monad passing voor de I/O (waar het genereren van random getallen blijkbaar, en terecht, ook onder valt). Het lijkt me dus dat je het best Glimi's advies kunt opvolgen en je gaan verdiepen in hoe Haskell werkt. (Met monadic IO Haskell vindt Google al heel wat).

  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
ok ga ik daar even mee aan de slag. thx!

  • Apollo_Futurae
  • Registratie: November 2000
  • Niet online
Appesteijn schreef op 20 June 2003 @ 10:36:
Waarom is het zo moeilijk om een lijst met random 1en en 0en te maken?
Als het deterministisch moet zijn:
Haskell:
1
2
lijstje :: [Int]
lijstje = randomRs (0,1) (mkStdGen 6)

(eventueel kun je de 6 vervangen door een op wat voor wijze dan ook verkregen seed)

Als het niet-deterministisch moet zijn:
Haskell:
1
2
3
4
lijstje :: IO [Int]
lijstje = do
  gen <- getStdGen
  randomRs (0,1) gen


Overigens vraag ik me af of het niet logischer is om [Bool] te genereren i.p.v. [Int], als je toch maar twee verschillende waarden nodig hebt.

N.b.: ik gebruik GHC 6.0

Pas de replâtrage, la structure est pourrie.


  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
Apollo_Futurae schreef op 20 juni 2003 @ 17:49:

[code]
Als het deterministisch moet zijn:
Haskell:
1
2
lijstje :: [Int]
lijstje = randomRs (0,1) (mkStdGen 6)

(eventueel kun je de 6 vervangen door een op wat voor wijze dan ook verkregen seed)

Overigens vraag ik me af of het niet logischer is om [Bool] te genereren i.p.v. [Int], als je toch maar twee verschillende waarden nodig hebt.
Dat is zeker handig, alleen moeten er evenveel 0en als 1en in. Ik was had zelf het volgende bedacht:

code:
1
2
geefRanGetal :: Int -> Int
geefRanGetal x = unsafePerformIO (rollDice x)


Alleen wilde mijn eerste idee, het genereren van een lijst posities en dan bij het toevoegen van een positie eerst kijken of die positie al voorkomt in de lijst, niet werken. Waarschijnlijk komen er steeds randomgetallen uit die al in de lijst zitten. en dan blijft ie maar door rekenen.

  • Apollo_Futurae
  • Registratie: November 2000
  • Niet online
Appesteijn schreef op 20 juni 2003 @ 18:09:
Dat is zeker handig, alleen moeten er evenveel 0en als 1en in.
Er zitten ook evenveel nullen als enen in - namelijk oneindig veel.
Dat klinkt flauw, maar wijst wel op een vaagheid in je vraagstelling: moeten er bij voorbeeld in 10 elementen 5 enen en 5 nullen zijn, of mogen het er best 4 resp. 6 zijn, als er van de 1000 maar wel 500 nullen en 500 enen zijn?

Pas de replâtrage, la structure est pourrie.


  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
Ok dat was idd niet echt duidelijk. Het is de bedoeling om een lijst van 250 nullen en 250 enen te maken. Maar dat moet natuurlijk voor elke lengte kunnen. Zelf zat ik nu te denken aan een functie met als input 1 lijst met getallen van 1...500 en nog een 2de lijst met 1...500. Dan laat ik telkens random 2 getallen uit lijst 1 halen en vul ik in lijst 2 die corresponderende posities in met een 1 een een 0. En zo ga ik door totdat lijst 1 leeg is en lijst 2 allemaal 1en en 0en bevat.

  • Apollo_Futurae
  • Registratie: November 2000
  • Niet online
ideetje: maak een functie die een willekeurige lijst 'schudt'.
uit de losse pols:
Haskell:
1
2
shuffle :: RandomGen g => g -> [a] -> [a]
shuffle generator = map snd . sortBy (\(a,_) (b,_) -> compare a b) . zip (randoms generator :: [Int])


nu kun je makkelijk je gewenste lijst maken door
shuffle (mkStdGen seed) $ take 250 (repeat 0) ++ take 250 (repeat 1)

Pas de replâtrage, la structure est pourrie.


  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
Okee, bedankt zo werkt het. Ik gebruik nu de geefRanGetal 1000 voor een willekeurige seed. Zou dat genoeg zijn? Ik moet ongeveer 100 a 200 random strings van 1en en 0en maken.

  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
Aargh, nu moet ik een file inlezen en zit ik weer met dat IO gebeuren. En het wil me maar niet lukken om die monad functie te begrijpen.

edit:


Ik stap maar over naar Java hopelijk lukt het daar wel in. In ieder geval bedankt allemaal.

[ Voor 30% gewijzigd door Appesteijn op 21-06-2003 18:55 ]


  • Apollo_Futurae
  • Registratie: November 2000
  • Niet online
wat is nu precies het probleem? het doet me pijn om iemand te zien overstappen op Java :'(.

Pas de replâtrage, la structure est pourrie.


  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
Ja uit principe wil ik het ook in Haskell doen en bovendien heb ik het idee dat ik haskell ook beter begrijp. Waar ik nu tegenaanloop is het volgende:

readFile geeft een IO String. En dan ben ik dus weer net zover als in het begin. Voorbeeld van de gelezen file:


1 (0.984907,0.344156) 10 69 141 156 160 207 226 358 452 474 495
2 (0.071221,0.777694) 13 63 119 147 219 248 306 335 371 412 423 433 445 465
3 (0.029400,0.407475) 7 51 218 235 283 391 432 462
4 ..........
.
.
500

Het eerste getal kan weg en ook de positie. (Voor de eerste dit dus: 1 (0.984907,0.344156)) daarna komt het getal met het aantal verbindingen en daarna met welke andere units hij een verbinding heeft. Ik wilde dit converteren naar [[[10],[69,141,156,160,207,226,358,452,474,495]], [[13],[63,119..........

Dus weer gewoon een [[Int]] en geen IO. Ik krijg die IO icm met do maar niet onder de knie.

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 10-08 15:15
Met welk gedeelte van de IO heb je problemen? Je moet er vanuit gaan dat als je een 'IO' functie wilt gebruiken, je altijd ook iets zult moeten opleverenen waar deze IO inzit. (ok, tenzij je een unsafeperformIO gebruikt, maar dat wil je eigenlijk niet...). Als jouw main-functie een IO oplevert, dan wordt deze uitgevoerd.

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • Apollo_Futurae
  • Registratie: November 2000
  • Niet online
Appesteijn schreef op 21 June 2003 @ 20:39:
readFile geeft een IO String. En dan ben ik dus weer net zover als in het begin.
Dit moet ook wel. De inhoud van je bestand zou kunnen veranderen tijdens het uitvoeren van je programma. Omdat niet bepaald is wanneer een functie geevalueerd wordt, moet aangegeven worden dat de inhoud van het bestand tijdstipafhankelijk is. Dit doe je dus m.b.v. de IO-monad.
Meer uitleg over monads en monadic IO in haskell vind je hier.
Voorbeeld van de gelezen file:


1 (0.984907,0.344156) 10 69 141 156 160 207 226 358 452 474 495
2 (0.071221,0.777694) 13 63 119 147 219 248 306 335 371 412 423 433 445 465
3 (0.029400,0.407475) 7 51 218 235 283 391 432 462
4 ..........
.
.
500

Het eerste getal kan weg en ook de positie. (Voor de eerste dit dus: 1 (0.984907,0.344156)) daarna komt het getal met het aantal verbindingen en daarna met welke andere units hij een verbinding heeft. Ik wilde dit converteren naar [[[10],[69,141,156,160,207,226,358,452,474,495]], [[13],[63,119..........
Zelf gebruik ik voor parsen altijd Parsec (meegeleverd met GHC). Ik zou eerst eens de docs doornemen. Als je specifieke vragen hebt of een voorbeeld nodig hebt roep je maar :).

Pas de replâtrage, la structure est pourrie.


  • Appesteijn
  • Registratie: Juni 2001
  • Niet online
Na een zondag lezen, proberen en nog meer lezen, heb ik besloten om de invoer maar gewoon in het bestand te copy pasten. Dus nog geen files inlezen. Nu kan ik het programma tenminste afmaken en dan zie ik op het einde wel of ik het inlezen en parsen van de input kan realiseren. Thx iedereen.

[ Voor 11% gewijzigd door Appesteijn op 23-06-2003 17:25 ]

Pagina: 1