7

人们普遍认为这unsafePerformIO不是类型安全的。这通常通过使用它来实现来演示unsafeCoerce

box :: IORef a
box = unsafePerformIO (newIORef undefined)
{-# NOINLINE box #-}

unsafeCoerce :: a -> b
unsafeCoerce a = unsafePerformIO $
  writeIORef box a >> readIORef box

正如我几年前所展示的,这种实现不是线程安全的。一个线程可以写入盒子,然后另一个线程可以在第一个线程可以读取之前再次写入盒子。哎呀!如何解决这个问题?

4

1 回答 1

9

正如我曾经展示过的那样,正确的做法是通过 an 使用强制IORef来产生unsafeCoerce函数本身,而不是产生其应用的个别结果。

box :: IORef x
box = unsafePerformIO (newIORef undefined)
-- This NOINLINE is essential. If this binding is inlined,
-- then unsafeCoerce = undefined.
{-# NOINLINE box #-}

unsafeCoerce :: a -> b
unsafeCoerce = unsafePerformIO $
  writeIORef box id >> readIORef box

-- Inlining this wouldn't break anything,
-- but it'd waste time with unnecessary IORef operations.
{-# NOINLINE unsafeCoerce #-}
于 2021-07-09T20:57:03.803 回答