作为shown in this answer,seq
与undefined
相结合,在涉及等式推理方面做了非常奇怪的事情,例如它可以使任何monad失败。另一个例子是this question。
最近我偶然发现evaluate :: a -> IO a
做了类似的事情 - 它只评估了WHNF的参数,但只评估了IO
动作。这似乎更安全,因为人们期望“在IO
我们可以做任何事情”。当然它不能在任何地方使用,但通常需要评估表达式以某种方式与IO
操作连接(比如强制生成线程在使用{{1}时评估计算而不是消耗线程} S)。
所以我想问一下,MVar
有多安全?是否有可能创建示例(当然涉及evaluate
),它会破坏像IO
这样的代码的推理?或者我可以将其视为seq
的安全替代品(如果特定程序可能的话)?
答案 0 :(得分:5)
不,您仍然会遇到seq
命令导致的相同问题,因为evaluate
的第一个参数中使用的任何monad都会破坏其monad规则。在ertes的答案中取消规则:
在Kleisli类别中,monad引起
return
身份态射和(<=<)
是构成。所以return
必须是一个(<=<)
的身份:return <=< x = x
这意味着您应该能够将return <=< x
替换为x
任何有效的monad,而无需更改程序的操作。
将其与evaluate
功能...
evaluate (return <=< undefined :: a -> Identity b) >> putStrLn "hello"
输出你好。通过将return <=< undefined
替换为undefined
来使用应该是等效语句:
evaluate (undefined :: a -> Identity b) >> putStrLn "hello"
会导致Prelude.undefined
例外。
这只发生在evaluate函数中。请注意,return
与evaluate
具有完全相同的类型签名。如果在上述命令中将evaluate
替换为return
,则两个命令的结果操作相同(它们输出hello
)。