gpt4 book ai didi

haskell - 我在滥用 unsafePerformIO 吗?

转载 作者:行者123 更新时间:2023-12-03 11:03:15 25 4
gpt4 key购买 nike

了解 unsafePerformIO (如何使用它以及何时使用它),我已经实现了一个用于生成唯一值的模块。

这是我所拥有的:

module Unique (newUnique) where

import Data.IORef
import System.IO.Unsafe (unsafePerformIO)

-- Type to represent a unique thing.
-- Show is derived just for testing purposes.
newtype Unique = U Integer
deriving Show

-- I believe this is the Haskell'98 derived instance, but
-- I want to be explicit, since its Eq instance is the most
-- important part of Unique.
instance Eq Unique where
(U x) == (U y) = x == y

counter :: IORef Integer
counter = unsafePerformIO $ newIORef 0

updateCounter :: IO ()
updateCounter = do
x <- readIORef counter
writeIORef counter (x+1)

readCounter :: IO Integer
readCounter = readIORef counter

newUnique' :: IO Unique
newUnique' = do { x <- readIORef counter
; writeIORef counter (x+1)
; return $ U x }

newUnique :: () -> Unique
newUnique () = unsafePerformIO newUnique'

令我高兴的是, package调用 Data.Unique选择了和我一样的数据类型;另一方面,他们选择了 newUnique :: IO Unique 类型。 ,但我想远离 IO如果可能的话。

这种实现危险吗?它可能会导致 GHC 改变使用它的程序的语义吗?

最佳答案

对待 unsafePerformIO作为对编译器的 promise 。它说“我保证您可以将此 IO 操作视为纯值,并且不会出错”。它很有用,因为有时您可以为使用不纯操作实现的计算构建纯接口(interface),但编译器无法验证何时是这种情况;而是 unsafePerformIO允许你 Handlebars 放在心上,发誓你已经验证了不纯的计算实际上是纯的,所以编译器可以简单地相信它是纯的。

在这种情况下, promise 是错误的。如果 newUnique那时是一个纯函数let x = newUnique () in (x, x)(newUnique (), newUnique ())将是等效的表达式。但是你会希望这两个表达式有不同的结果;一对相同 Unique 的副本一种情况下的值,以及一对两个不同的Unique另一方的值(value)观。使用您的代码,真的无法说出这两个表达式的含义。它们只能通过考虑程序在运行时执行的实际操作顺序来理解,而对它的控制正是您在使用 unsafePerformIO 时放弃的内容。 . unsafePerformIO表示是否将任一表达式编译为 newUnique 的一次执行并不重要或者两个,并且 Haskell 的任何实现在每次遇到此类代码时都可以自由选择它喜欢的任何内容。

关于haskell - 我在滥用 unsafePerformIO 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19371636/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com