对 MVar 进行采样,我可以避免 unsafePerformIO 吗?

Sampling an MVar, can I avoid unsafePerformIO?

我有

sample :: MVar a -> IO [a]
sample v = do
   a <- takeMVar v
   pure (a:unsafePerformIO (sample v))

这对我来说似乎是对 unsafePerformIO 的合法使用。但我很想知道如何避免它!已经有这种用途的模式了吗?

你可以使用一个线程实现类似的功能,一个ChangetChanContents:

sample :: MVar a -> IO [a]
sample v = do
   c <- newChan
   forkIO $ forever $ takeMVar v >>= writeChan c
   getChanContents c   

thread/getChanContents 方法稍微好一些,因为至少你可以依赖 MVar 被连续使用。相反,unsafePerformIO 方法将 运行 takeMVar 在不可预测的点,使 putMVar 以类似不可预测的方式阻塞。当然,getChanContents 方法将缓冲所有数据,可能需要更多内存。

但是,这两种方法在本质上都类似于惰性 IO,我认为最好避免这种情况。