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?