Po pierwsze, przepraszam za tytuł nieopisujący. Ponieważ nie mam pojęcia, co się właściwie dzieje, nie mogę zrobić tego bardziej konkretnego.Dlaczego GHCI "zatrzymuje się" w stanie błędu po błędzie?
Teraz na moje pytanie. I wprowadziły następujące fragment do problemu 23 99 Haskell problems, które należy losowo wybrać n
pozycji z listy:
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)
Teraz kiedy załadować to w ghci
to działa poprawnie z ważnych argumentów:
*Main> rndSelectIO' "asdf" 2 >>= putStrLn
af
jednak dziwne rzeczy dzieją się, gdy używany jest indeks, który jest poza zakresem:
*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
Jak widać, po 2 (dla mnie) zdarzają się niespodziewane rzeczy:
- Zamiast bezpośrednio podawać błąd, najpierw drukuje permutację wejścia.
- Po tym, jak raz wystąpił błąd, nie będzie już więcej wykonywany.
Podejrzewam, że 1. ma związek z leniwą oceną, ale absolutnie nie mam pojęcia, dlaczego 2. się dzieje. Co tu się dzieje?
Każda linia w sesji interaktywnej znajduje się wewnątrz tego samego niejawnego wyrażenia 'do', które nigdy się nie kończy, więc każda linia przekazuje swój wynik do następnego. – chepner