Выборка 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 подход будет буферизовать все данные, возможно, требуя больше памяти.

Однако оба подхода по сути похожи на ленивый ввод-вывод, которого, на мой взгляд, лучше избегать.

Другие вопросы по тегам