Haskell通常被引用为纯函数式语言的示例.鉴于存在,这怎么可能是合理的System.IO.Unsafe.unsafePerformIO?
编辑:我认为"纯功能"意味着不可能将不纯的代码引入程序的功能部分.
haskell type-systems functional-programming referential-transparency unsafe-perform-io
为了熟悉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 …我在哈斯克尔图书馆的限制区闲逛,发现了这两个邪恶的咒语:
{- System.IO.Unsafe -}
unsafeDupablePerformIO  :: IO a -> a
unsafeDupablePerformIO (IO m) = case runRW# m of (# _, a #) -> a
{- Data.ByteString.Internal -}
accursedUnutterablePerformIO :: IO a -> a
accursedUnutterablePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
然而,实际差异似乎只是在runRW#和之间($ realWorld#)。我对他们在做什么有一些基本的了解,但我没有得到使用一个而不是另一个的真正后果。有人可以解释我有什么区别吗?
我经常在Haskell代码中找到这种模式:
options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar
...
doSomething :: Foo -> Bar
doSomething = unsafePerformIO $ do
  opt <- readMVar options
  doSomething' where ...
基本上,一个人有一个选项或类似的记录,最初是在程序开始时设置的.由于程序员很懒惰,他不想options在整个程序中携带记录.他定义了一个MVar保持它 - 由丑陋的使用定义unsafePerformIO.程序员确保状态只设置一次,并且在任何操作发生之前.现在程序的每个部分都必须unsafePerformIO再次使用,只是为了提取选项.
在我看来,这样的变量被认为是实用的纯粹(不要打败我).是否有一个库抽象出这个概念,并确保变量只设置一次,即在初始化之前没有调用,并且不需要写unsafeFireZeMissilesAndMakeYourCodeUglyAnd DisgustingBecauseOfThisLongFunctionName
haskell global-variables purely-functional unsafe-perform-io
我正在为C中的库创建一个FFI模块,它希望在其他任何东西之前调用一次非重入函数.这个调用是幂等的,但是有状态的,所以我可以在每个Haskell调用中调用它.但它很慢并且由于不可重入而可能导致冲突.
那么这是使用unsafePerformIO的合适时机吗?我可以将Bool包装在一个不安全的IORef或MVar中,通过忽略后续调用(全局隐藏IORef状态为False的调用)使这些初始化调用成为幂等的.
如果没有,这样做的正确方法是什么?
最好的方法是什么?unsafePerformIO?模板Haskell?别的什么?我从来没有使用过这些,所以我不知道使用它们的许多细节.
请注意,程序将在每次运行时进行编译,因此在编译时或运行时生成字符串无关紧要.我还需要在整个代码中的大量位置使用此字符串,因此我无法以"正确"方式执行此操作并将其作为IO操作,这将需要将太多其他代码放入IO monad中.
我在haskell中编写了一个函数,它接受一些参数,如Word32,String(忽略currying)并输出IO Word32.现在,这是一个真正意义上的函数:对于相同的输入,输出将始终相同.没有副作用.函数返回IO Word32而不是Word32的原因是该函数在循环中多次更新许多32位线性反馈移位寄存器(lfsr)和其他寄存器,以便计算最终的Word32输出.
我的问题是:鉴于此函数实际上没有副作用,是否可以在函数实现中隐藏这些寄存器更新,以便该函数返回Word32而不是IO Word32?如果是这样,怎么样?
monads haskell functional-programming referential-transparency unsafe-perform-io
我有一个数据类型,其中包含IORef作为一个重要元素.这意味着没有一种干净的方法可以使它成为show类型类的成员.这不是太糟糕,因为我print在这种类型的IO monad中有一个函数.但是在GHCi中很烦人,因为每当我返回其中一个东西时,我都会收到错误声明它无法显示.
有没有办法让IOC无论如何在IO monad中运行,使用IO动作来显示结果?如果没有,是否会对写作产生任何负面影响show a = unsafePerformIO $ print a?  
我unsafePerformIO最近一直在读,我想问你一件事.我很清楚,真正的语言应该能够与外部环境进行交互,因此unsafePerformIO有些合理.
但是,据我所知,我不知道有什么快速的方法来了解一个看似纯粹的(从类型判断)接口/库是否真的纯粹没有检查代码搜索调用unsafePerformIO(文档可以省略到提到它).我知道只有当你确定引用透明度得到保证时才应该使用它,但我想知道它.
众所周知,这unsafePerformIO不是类型安全的。这通常通过使用它来实现来证明unsafeCoerce:
box :: IORef a
box = unsafePerformIO (newIORef undefined)
{-# NOINLINE box #-}
unsafeCoerce :: a -> b
unsafeCoerce a = unsafePerformIO $
  writeIORef box a >> readIORef box
正如我几年前所展示的,这个实现不是线程安全的。一个线程可以写入盒子,然后另一个线程可以在第一个线程可以读取之前再次写入盒子。哎呀!如何解决这个问题?