First of all, my apologies for the non-descriptive title. Since I have no idea what's actually going on I can't really make it any more specific.
Now for my question. I have implemented the following snippet for problem 23 of the 99 Haskell problems, which should randomly select n
items from a list:
rndSelect' :: RandomGen g => [a] -> Int -> g -> ([a], g)
rndSelect' _ 0 gen = ([], gen)
rndSelect' [] _ _ = error "Number of items requested is larger than list"
rndSelect' xs n gen = ((xs !! i) : rest, gen'')
where (i, gen') = randomR (0, length xs - 1) gen
(rest, gen'') = (rndSelect' (removeAt xs i) (n - 1) gen')
rndSelectIO' :: [a] -> Int -> IO [a]
rndSelectIO' xs n = getStdRandom $ rndSelect' xs n
removeAt :: [a] -> Int -> [a]
removeAt xs n
| length xs <= n || n < 0 = error "Index out of bounds"
| otherwise = let (ys, zs) = splitAt n xs
in ys ++ (tail zs)
Now when I load this in ghci
this works correctly for valid arguments:
*Main> rndSelectIO' "asdf" 2 >>= putStrLn
af
However, strange things happen when I use an index that is out of bounds:
*Main> rndSelectIO' "asdf" 5 >>= putStrLn
dfas*** Exception: Number of items requested is larger than list
*Main> rndSelectIO' "asdf" 2 >>= putStrLn
*** Exception: Number of items requested is larger than list
As you can see, the following 2 (for me) unexpected things happen:
- Instead of directly giving an error it first print a permutation of the input.
- After it has given an error once, it won't execute at all anymore.
I suspect that 1. has to do with lazy evaluation, but I have absolutely no clue why 2. happens. What's going on here?