gpt4 book ai didi

haskell - 如何强制评估 `unsafePerformIO` 内的 IO 操作?

转载 作者:行者123 更新时间:2023-12-05 09:17:01 25 4
gpt4 key购买 nike

import System.IO.Unsafe

main :: IO ()
main = do
_ <- return $ unsafePerformIO $ do
print "test2"
print "test"

以上仅输出 test(当通过 runghc 运行时),我假设由于 Haskell 的惰性性质,第一个 IO 操作实际上没有得到评估。我怎样才能强制它评估和执行操作?

以上仅用于调试目的。

最佳答案

为了执行 IO 副作用,需要强制使用 unsafePerformIO 创建的“纯”值(即,至少评估为 WHNF)。

不幸的是,您的 main 函数:

main = do
_ <- return $ unsafePerformIO $ do
print "test2"
print "test"

脱糖(根据 Haskell98 报告)为:

main = let ok _ = do { print "test" }
ok _ = fail "..."
in return (unsafePerformIO (print "test2")) >>= ok

根据 monad 法则等价于:

main = let ok _ = do { print "test" }
ok _ = fail "..."
in ok (unsafePerformIO (print "test2"))

遗憾的是,let 绑定(bind)的第一部分:

let ok _ = do { print "test2" }

在调用时不使用——因此不强制——它的参数,因此忽略“纯”不安全 IO 操作。

由于将“纯”值与其构造函数(即 ())进行模式匹配,强制该值并因此执行不安全的操作,如果您这样写:

main = do
() <- return $ unsafePerformIO $ do
print "test2"
print "test"

这样就可以了。

还有其他方法可以强制执行此操作。您可以明确地进行模式匹配:

main = do
case unsafePerformIO (print "test2") of
() -> return ()
print "test"

或者像这样使用seq:

main = do
unsafePerformIO (print "test2") `seq` print "test"

或者像这样:

main = do
unsafePerformIO (print "test2") `seq` return ()
print "test"

或者使用严格的求值运算符:

main = do
return $! unsafePerformIO (print "test2")
print "test"

您还可以按照@Chris Stryczynski 的建议使用BangPatterns 扩展。

我不确定哪个最好,但我倾向于使用 ($!) 运算符作为最惯用的运算符。

如@Carl 所述,出于调试目的,使用 Debug.Trace 中的 trace 通常比直接调用 unsafePerformIO 更明智,两者因为它是从纯代码打印调试信息的标准方式,而且因为实现比简单的 unsafePerformIO 更周到一点。 putStrLn。但是,它可能会出现相同的问题:

import Debug.Trace
main = do
return $ trace "test2" () -- won't actually print anything
print "test"

相反,您需要强制它的值,也许使用上述方法之一:

import Debug.Trace
main = do
return $! trace "test2" () -- with ($!) this works
print "test"

当@Carl 说 trace 有一个 API 可以解决这个问题时,他的意思是您通常在以下情况下使用 trace:

let value_i_actually_use = trace "my message" value_of_the_trace_expression

当您实际使用(评估)trace 表达式的值时,将显示消息。

然后

关于haskell - 如何强制评估 `unsafePerformIO` 内的 IO 操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48977455/

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