Я заметил эту идиому в Data.Unique:Насколько безопасен `unsafePerformIO (newTVarIO 0)`?
uniqSource :: TVar Integer
uniqSource = unsafePerformIO (newTVarIO 0)
{-# NOINLINE uniqSource #-}
ли это гарантированно работать только один раз?
Я заметил эту идиому в Data.Unique:Насколько безопасен `unsafePerformIO (newTVarIO 0)`?
uniqSource :: TVar Integer
uniqSource = unsafePerformIO (newTVarIO 0)
{-# NOINLINE uniqSource #-}
ли это гарантированно работать только один раз?
В GHC, да. Для получения дополнительной информации см. the documentation; существует вариант unsafeDupablePerformIO
, который может выполняться несколько раз, что позволяет избежать накладных расходов, связанных с достижением этой гарантии.
Обратите внимание, что unsafePerformIO
для создания изменяемых переменных небезопасно вообще; как описано в документации, вы можете создать полиморфную ссылку и использовать ее для реализации unsafeCoerce
. Это не то, что вы, скорее всего, сделаете случайно, и это не относится к рассматриваемому коду (так как тип ссылки указан явно).
Пакет safe-globals содержит в себе эту «идиому» (полезную в некоторых случаях, это generally considered an antipattern и ее нельзя использовать в нормальном коде) таким образом, чтобы обеспечить безопасность.
См. Также мой previous answer на unsafePerformIO
и предостережение, которое необходимо использовать при его применении.
Я уверен, что это относится ко всем другим реализациям; особая забота GHC, чтобы избежать повторного выполнения, необходима только в поточной настройке, и я не знаю никаких других потоковых реализаций Haskell. GHC является единственной реализацией, которую люди действительно используют в наши дни, хотя ...
Как правило, 'unsafePerformIO' следует использовать только как деталь реализации кода библиотеки, а затем вы должны использовать его только потому, что вы совершенно уверен, что нет абсолютно никакого другого способа добиться такой же производительности/поведения. Я не совсем уверен, почему я почувствовал необходимость сказать, что здесь, так как на вопрос не на 100%, но там вы идете. –
Связанные: http://stackoverflow.com/questions/6076129/ – fuz