Good evening everybody! This is a question concerning Haskell. I want to get x
random elements from a list by using a function.
The problem I get is that when I try to use random numbers, with randomRIO
. I get the error message:
No instance for (Control.Monad.IO.Class.MonadIO [])
arising from a use of `randomRIO'
This error message suddenly goes away when i use print or return. But I dont want to use print
, and return
messes up the output to a nested list [[a]]
instead of [a]
.
Does any of you have a tip on what I can do to extract x
random elements from the list, in the form of a list?
The type would be something like this. xRanElems :: [a] -> Int -> [a]
where the second Int
is an accumulator but I got that covered.
xRanElems xs n = do
r <- randomRIO (0, n)
xRanElems2 xs n r
where n
is just length xs - 1
xRanElems2 xs n r = (xs !! r) : (xRanElems (xsWithOutSelectedElem xs r) (n-1))
Thankful for any input!
CodePudding user response:
The following typechecks:
import System.Random
xRanElems :: [a] -> Int -> IO [a]
xRanElems xs n = do
-- randomRIO :: Random t
-- => (t, t) -> IO t
r <- randomRIO (0, n) -- r :: Int
xRanElems2 xs n r
xRanElems2 :: [a] -> Int -> Int -> IO [a]
xRanElems2 xs n r =
let (a,b:c) = splitAt r xs
in
fmap (b :) -- [a] -> [a]
(xRanElems -- IO [a] -> IO [a]
(a c) (n-1))
Trying to run it, e.g. with xRanElems [1..3] 2
, reveals that it loops forever.
This is because you need to provide the base case in xRanElems
to stop the recursion, e.g. return
ing []
when n <= 0
.
The above code also contains an off-by-1 error which you're invited to fix.