I recently started to learn Haskell. I'm trying to write a program that pick a random element of array:
import System.Random
randomInt :: (Int, Int) -> IO Int
randomInt range = randomRIO range :: IO Int
choseRandom :: [a] -> a
choseRandom list =
length list
>>=
(\l -> randomInt(0,l-1))
>>=
(\num -> (list !! num))
main :: IO ()
main = undefined
and I get the following error:
Build FAILED
C:\Users\User\Haskell\Real\src\Main.hs: line 7, column 9:
Couldn't match expected type `IO Int' with actual type `Int'
In the return type of a call of `length'
In the first argument of `(>>=)', namely `length list'
In the first argument of `(>>=)', namely
`length list >>= (\ l -> randomInt (0, l - 1))'
what I'm doing wrong? It's hard for me to deal monads for first times
It's hard for me to deal monads for first times
Yes, and you make it harder by avoiding syntactic support. Just write it thus:
choseRandom list = do
let l = length list
num <- randomInt(0,l-1)
return (list !! num)
Doesn't this look much better?
Now to the point: the randomRIO
function, as their type indicates, uses some global state (probably the system timer). Hence you can use results from RandomRIO
only in the IO
Monad.
An alternative would be to initialize a random generator in the main
function, and pass this generator down to pure functions that need "random" values.
Since you're using IO inside choseRandom
you need to change the type signature:
choseRandom :: [a] -> IO a
secondly, you don't need to use >>=
to get the length of the list. >>=
has type
Monad m => m a -> (a -> m b) -> m b
The type of length
is [a] -> Int
, so the type of length list
is Int
, which is not a monad.
You can calculate it directly when calling randomInt
:
choseRandom :: [a] -> IO a
choseRandom list =
randomInt(0, length list) >>= (\num -> return (list !! num))
which is the same as
choseRandom :: [a] -> IO a
choseRandom list = fmap (\num -> (list !! num)) (randomInt(0, length list))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With