Stworzyłem ten mały program, który tworzy długo działający thunk, który ostatecznie kończy się niepowodzeniem z wyjątkiem. Następnie wiele wątków próbuje to ocenić.Jeśli thunk powoduje wyjątek, czy wyjątek jest zachowywany w wyniku thunk?
import Control.Monad
import Control.Concurrent
import Control.Concurrent.MVar
main = do
let thunk = let p = product [1..10^4]
in if p `mod` 2 == 0 then error "exception"
else()
children <- replicateM 2000 (myForkIO (print thunk))
mapM_ takeMVar children
-- | Spawn a thread and return a MVar which can be used to wait for it.
myForkIO :: IO() -> IO (MVar())
myForkIO io = do
mvar <- newEmptyMVar
forkFinally io (\_ -> putMVar mvar())
return mvar
Zwiększenie liczby wątków ma wyraźnie żadnego wpływu na obliczenia, co sugeruje, że nie udało thunk utrzymuje wyjątek jako wynik. Czy to prawda? Czy to zachowanie jest udokumentowane/określone gdzieś?
Update: Zmiana linii forkFinally
do
forkFinally io (\e -> print e >> putMVar mvar())
potwierdza, że każda nić nie z wyjątkiem.
Wyjątkiem * jest * wartość wyrażenia. Co jeszcze może oceniać wyrażenie wiele razy? – Carl
@Carl Tego właśnie podejrzewam, ale chcę być tego pewien. Może również spróbować ponownie przeliczyć wartość ponownie. –
Znam wewnętrzne GHC, w przeciwnym razie nie mógłbym stworzyć narzędzi takich jak 'ghc-heap-view', więc nie jestem pewien, czego więcej potrzebujesz. Czy możesz wyjaśnić swoje pytanie, jeśli moja odpowiedź nie jest wystarczająco pomocna? –