Насколько безопасен `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 - единственная реализация, которую люди действительно используют в наши дни, хотя...