我在Data.Unique中注意到了这个成语:
uniqSource :: TVar Integer
uniqSource = unsafePerformIO (newTVarIO 0)
{-# NOINLINE uniqSource #-}
是否保证只运行一次?
我在Data.Unique中注意到了这个成语:
uniqSource :: TVar Integer
uniqSource = unsafePerformIO (newTVarIO 0)
{-# NOINLINE uniqSource #-}
是否保证只运行一次?
在 GHC 中,是的。1查看文档了解更多信息;有一个变体unsafeDupablePerformIO
可以多次执行,避免了专门用于实现此保证的开销。
请注意,unsafePerformIO
创建可变变量通常是不安全的。如文档中所述,您可以创建多态引用并使用它来实现unsafeCoerce
. 不过,这不是您可能会意外做的事情,并且它不适用于有问题的代码(因为引用的类型是明确指定的)。
safe-globals包以确保安全的方式抽象了这个“惯用语”(虽然在某些情况下很有用,但它通常被认为是一种反模式,不应在正常代码中使用)。
另请参阅我之前的回答以及unsafePerformIO
应用时必须注意的事项。
1我很确定它也适用于所有其他实现;GHC 为避免重复执行而采取的特殊措施仅在线程设置中是必要的,而且我不知道 Haskell 的任何其他线程实现。GHC 是当今人们真正使用的唯一实现,尽管......