まず、タイトルが意味不明で申し訳ありません。実際に何が起こっているのかわからないので、これ以上具体的にすることはできません。
さて、私の質問です。Haskellの 99 の問題のうち 23 の問題について、次のスニペットを実装しました。これはn
、リストから項目をランダムに選択する必要があります。
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)
これをロードするとghci
、有効な引数に対して正しく機能します。
*Main> rndSelectIO' "asdf" 2 >>= putStrLn
af
ただし、範囲外のインデックスを使用すると、奇妙なことが起こります。
*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
ご覧のとおり、次の 2 つの (私にとって) 予期しないことが起こります。
- エラーを直接与える代わりに、最初に入力の順列を出力します。
- 一度エラーが発生すると、まったく実行されなくなります。
1. は遅延評価と関係があるのではないかと思いますが、なぜ 2. が起こるのかまったくわかりません。何が起きてる?