如何使用unsafePerformIO来编写unsafeCoerce?

众所周知,这unsafePerformIO不是类型安全的。这通常通过使用它来实现来证明unsafeCoerce

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

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

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

回答

正如我曾说过的那样,正确的方法是通过 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 #-}

  • 我承认我对“正确的方式”嗤之以鼻:我们正在创造一种可憎的东西,但是嘿,我们应该小心不要以错误的方式这样做!;-)
  • @chi,是的,这有点傻,但我觉得很有趣。

以上是如何使用unsafePerformIO来编写unsafeCoerce?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>