Mar*_*ark 7 haskell lazy-evaluation
在黑客入侵时,我发现了这个:
!() <- atomicModifyIORef (eoExeCache eo) $ \m' ->
(Map.insert name epath m', ())
Run Code Online (Sandbox Code Playgroud)
HLint说:"删除那件事".但我认为这不是一个错字.有没有理由写!()?
如果有疑问(而不是匆忙),请参阅规范.
表达方式
do !() <- foo
bar
Run Code Online (Sandbox Code Playgroud)
des to to to
let ok !() = bar
ok _ = fail ..
in foo >>= ok
Run Code Online (Sandbox Code Playgroud)
let ok = \x -> case x of !() -> bar
_ -> fail ...
in foo >>= ok
Run Code Online (Sandbox Code Playgroud)
现在爆炸模式的规则在GHC用户指南中,因为它是非标准的haskell.我们发现我们可以将其改写成
let ok = \x -> x `seq` (case x of () -> bar
_ -> fail ...)
in foo >>= ok
Run Code Online (Sandbox Code Playgroud)
现在seq的定义是它的论证是⊥与否.所以要么x是⊥,要么是第二个参数seq,即case x of ...根据模式匹配的语义也是⊥ .或者x不是⊥,seq等于它的第二个参数.在任何一种情况下,上面的代码都是相同的
let ok = \x -> case x of () -> bar
_ -> fail ...
in foo >>= ok
Run Code Online (Sandbox Code Playgroud)
追溯这些步骤,相当于
do () <- foo
bar
Run Code Online (Sandbox Code Playgroud)
总而言之:没有理由在do表达式中这样做.
但是,它们之间存在差异
let () = foo
in bar
Run Code Online (Sandbox Code Playgroud)
(foo永远不会评估的地方)和
let !() = foo
in bar
Run Code Online (Sandbox Code Playgroud)
因为let-expressions在爆炸模式的语义上有特殊的规定.