鉴于此代码段:
someFunction x = print x `seq` 1
main = do print (someFunction "test")
Run Code Online (Sandbox Code Playgroud)
代码执行时为什么不print x打印test?
$./seq_test
1
Run Code Online (Sandbox Code Playgroud)
如果我替换它error我可以检查左操作数seq 是否确实被评估.
我怎样才能达到预期的输出:
test
1
Run Code Online (Sandbox Code Playgroud)
只修改someFunction?
lef*_*out 11
评估一个IO动作什么都不做.那就对了!
如果您愿意,IO类型的值只是"指令列表".因此,所有你与该做的seq是强制程序,以确保1什么应该,如果是真正的动作来完成使用.使用动作与评估无关,它意味着单独将其与main呼叫绑定.但是,正如你所说,因为这someFunction是一个非monadic签名的函数,这在这里不可能发生.
你可以做什么...... 但不要是
import Foreign
someFunction x = unsafePerformIO (print x) `seq` 1
Run Code Online (Sandbox Code Playgroud)
这实际上将评估与IO执行相结合.这通常在Haskell中是一个非常糟糕的主意,因为评估可能发生在完全不可预测的顺序上,可能发生的次数可能比你想象的要多(因为编译器假设参考透明度),以及其他混乱场景.
正确的解决方案是将签名更改为monadic:
someFunction :: Int -> IO Int
someFunction x = do
print x
return 1
main = do
y <- someFunction "test"
print y
Run Code Online (Sandbox Code Playgroud)
1事实上,即使没有,程序也尽可能确定seq.只有通过执行操作才能获得更多细节.