Выборка MVar, могу ли я избежать unsafePerformIO?
Я имею
sample :: MVar a -> IO [a]
sample v = do
a <- takeMVar v
pure (a:unsafePerformIO (sample v))
который представляется законным использованием unsafePerformIO
мне. Но мне очень интересно знать, как этого избежать! Есть ли шаблон для этого использования уже?
1 ответ
Решение
Вы можете реализовать аналогичную функцию, используя поток, Chan
а также getChanContents
:
sample :: MVar a -> IO [a]
sample v = do
c <- newChan
forkIO $ forever $ takeMVar v >>= writeChan c
getChanContents c
Нить/ getChanContents
подход немного лучше, так как по крайней мере вы можете положиться на MVar
быть постоянно взятым. Вместо этого unsafePerformIO
подход будет работать takeMVar
в непредсказуемых точках, делая putMVar
Блокировка таким же непредсказуемым образом. Конечно, getChanContents
подход будет буферизовать все данные, возможно, требуя больше памяти.
Однако оба подхода по сути похожи на ленивый ввод-вывод, которого, на мой взгляд, лучше избегать.