Насколько безопасен `unsafePerformIO (newTVarIO 0)`?

Я заметил эту идиому в Data.Unique:

uniqSource :: TVar Integer
uniqSource = unsafePerformIO (newTVarIO 0)
{-# NOINLINE uniqSource #-}

Гарантируется ли запуск только один раз?

1 ответ

Решение

В GHC да.1 См. Документацию для получения дополнительной информации; есть вариант unsafeDupablePerformIO это может быть выполнено многократно, что позволяет избежать накладных расходов, связанных с достижением этой гарантии.

Обратите внимание, что unsafePerformIO создавать изменяемые переменные вообще не безопасно; как описано в документации, вы можете создать полиморфную ссылку и использовать ее для реализации unsafeCoerce, Это не то, что вы, вероятно, будете делать случайно, и это не относится к рассматриваемому коду (поскольку тип ссылки указан явно).

Пакет safe-globals абстрагирует эту "идиому" (хотя в некоторых случаях она полезна, она обычно считается антипаттерном и не должна использоваться в обычном коде) таким образом, чтобы обеспечить безопасность.

Смотрите также мой предыдущий ответ на unsafePerformIO и осторожность, которая должна быть использована при его применении.

1 Я уверен, что это применимо и ко всем другим реализациям; Особая забота, которую GHC предпринимает, чтобы избежать повторного выполнения, необходима только в поточной настройке, и я не знаю каких-либо других поточных реализаций Haskell. GHC - единственная реализация, которую люди действительно используют в наши дни, хотя...

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