这里真的需要单位的爆炸模式吗?
Is a bang pattern on unit really needed here?
在破解 Stack 时,我发现 this:
!() <- atomicModifyIORef (eoExeCache eo) $ \m' ->
(Map.insert name epath m', ())
HLint 说:“删除那个东西”。但我不认为这是一个错字。有什么理由写 !()
?
如有疑问(并不着急)请咨询 specification。
表达式
do !() <- foo
bar
desugars 到
let ok !() = bar
ok _ = fail ..
in foo >>= ok
由 rules for function definition 这相当于
let ok = \x -> case x of !() -> bar
_ -> fail ...
in foo >>= ok
现在 rules for bang patterns 在 GHC 用户指南中,因为它是非标准的 haskell。在那里我们发现我们可以将其重写为
let ok = \x -> x `seq` (case x of () -> bar
_ -> fail ...)
in foo >>= ok
现在seq
is defined in terms of its argument being ⊥ or not. So either x
is ⊥, but then the second argument to seq
, namely the case x of ...
is also ⊥ according to the semantics of pattern matching。或者 x
不是 ⊥,并且 seq
等于它的第二个参数。在任何一种情况下,上面的代码都等同于
let ok = \x -> case x of () -> bar
_ -> fail ...
in foo >>= ok
追溯这些步骤,相当于
do () <- foo
bar
总而言之:没有理由在 do
表达式中这样做。
但是,
let () = foo
in bar
(其中 foo
永远不会被评估)和
let !() = foo
in bar
因为 let 表达式在 semantics for bang patterns.
中有特殊规定
在破解 Stack 时,我发现 this:
!() <- atomicModifyIORef (eoExeCache eo) $ \m' ->
(Map.insert name epath m', ())
HLint 说:“删除那个东西”。但我不认为这是一个错字。有什么理由写 !()
?
如有疑问(并不着急)请咨询 specification。
表达式
do !() <- foo
bar
desugars 到
let ok !() = bar
ok _ = fail ..
in foo >>= ok
由 rules for function definition 这相当于
let ok = \x -> case x of !() -> bar
_ -> fail ...
in foo >>= ok
现在 rules for bang patterns 在 GHC 用户指南中,因为它是非标准的 haskell。在那里我们发现我们可以将其重写为
let ok = \x -> x `seq` (case x of () -> bar
_ -> fail ...)
in foo >>= ok
现在seq
is defined in terms of its argument being ⊥ or not. So either x
is ⊥, but then the second argument to seq
, namely the case x of ...
is also ⊥ according to the semantics of pattern matching。或者 x
不是 ⊥,并且 seq
等于它的第二个参数。在任何一种情况下,上面的代码都等同于
let ok = \x -> case x of () -> bar
_ -> fail ...
in foo >>= ok
追溯这些步骤,相当于
do () <- foo
bar
总而言之:没有理由在 do
表达式中这样做。
但是,
let () = foo
in bar
(其中 foo
永远不会被评估)和
let !() = foo
in bar
因为 let 表达式在 semantics for bang patterns.
中有特殊规定