I have
sample :: MVar a -> IO [a]
sample v = do
a <- takeMVar v
pure (a:unsafePerformIO (sample v))
which appears to be a legitimate use of unsafePerformIO
to me. But I am very interested to know how to avoid it! Is there a pattern for this use already?
You can implement a similar function using a thread, a Chan
and getChanContents
:
sample :: MVar a -> IO [a]
sample v = do
c <- newChan
forkIO $ forever $ takeMVar v >>= writeChan c
getChanContents c
The thread/getChanContents
approach is slightly better, since at least you can rely on the MVar
being continuously taken. Instead, the unsafePerformIO
approach will run takeMVar
at impredictable points, making the putMVar
s blocking in a similarly impredictable way. Of course, the getChanContents
approach will buffer all the data, possibly requiring more memory.
However, both approaches are essentially similar to lazy IO, which is best to be avoided, in my opinion.