真的需要单位的爆炸模式吗?

Mar*_*ark 7 haskell lazy-evaluation

在黑客入侵时,我发现了这个:

!() <- atomicModifyIORef (eoExeCache eo) $ \m' ->
    (Map.insert name epath m', ())
Run Code Online (Sandbox Code Playgroud)

HLint说:"删除那件事".但我认为这不是一个错字.有没有理由写!()

Joa*_*ner 6

如果有疑问(而不是匆忙),请参阅规范.

表达方式

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在爆炸模式语义上有特殊的规定.