Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If statement using IO Int haskell

I have a game , user vs computer and I want to randomly choose who starts the game. I have

a = getStdRandom $ randomR (0, 1)

This gets a random number 0 or 1. However it is a IO Int, so I can't have an if statement comparing it to a number like

if a == 0 then userStarts else computerStarts 

I have tried to compare IO Int with IO Int and it doesn't work, and I have also tried

Converting IO Int to Int

I am very new to Haskell, not sure how to approach this. Code details requested:

randomNumber =  getStdRandom $ randomR (0, length symbols - 5) --  this will be 0 or 1
randomNumber2 =  getStdRandom $ randomR (0, length symbols - 5) -- according to 
                     -- the solution I need another function returning IO int.

a = do
   x <- randomNumber
   randomNumber2 $ pureFunction x

Error I get:

• Couldn't match expected type ‘t0 -> IO b
                  with actual type ‘IO Int’
    • The first argument of ($) takes one argument,
      but its type ‘IO Int’ has none
      In a stmt of a 'do' block: randomNumber2 $ pureFunction x
      In the expression:
        do x <- randomNumber
           randomNumber2 $ pureFunction x

    • Relevant bindings include
        a :: IO b
          (bound at Path:87:1)

    randomNumber2 $ pureFunction x

Path:89:20: error:
    Variable not in scope: pureFunction :: Int -> t0

     randomNumber2 $ pureFunction x

2 Answers

When you say a = getStdRandom $ randomR (0,1) you are saying "let a be the action of getting a random value between 0 and 1". What you want is within some function's do block a <- getStdRandom $ randomR (0,1) which is "let a be the result of running the action of getting a random value between 0 and 1".

As such:

import System.Random

main :: IO ()
main = do
  a <- getStdRandom $ randomR (0, 1 :: Int)
  if a == 0 then userStarts else computerStarts

-- Placeholders for completeness
userStarts, computerStarts :: IO ()
userStarts = putStrLn "user"
computerStarts = putStrLn "computer"

N.B. I specified the 1 is an int or else the compiler won't know if you want a random int, int64, double, float, or something else entirely.

EDIT: @monocell makes a good point that generating an int in a range just to get a boolean is somewhat indirect. You can just directly generate a boolean result and this requires no range:

  a <- getStdRandom random
  if a then userStarts else computerStarts
like image 199
Thomas M. DuBuisson Avatar answered Apr 23 '26 16:04

Thomas M. DuBuisson


Not sure how your code looks like, but have you tried doing what the linked resource recommends (using the do block)?

do
   (result, newGenerator) <- randomR (0, 1) generator
   -- ...

That will get you access to result, which is of the same type as 0 and 1.

Can you show your code/the error you get?

like image 24
Piotr Justyna Avatar answered Apr 23 '26 15:04

Piotr Justyna



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!