Do inner bang patterns always force outer constructors in Haskell?

一笑奈何 提交于 2019-12-04 18:55:21

问题


In Haskell, is there ever a situation where for a data type

{-# LANGUAGE BangPatterns #-}
import Control.DeepSeq

data D = D Int

the instance

instance NFData D where
  rnf (D !_) = ()

can have a different effect than the instance with another outer !:

instance NFData D where
  rnf !(D !_) = ()

My research:

  • https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/glasgow_exts.html#bang-patterns-informal only talks about let bindings (like this answer), which I think doesn't apply for function pattern matches like this.
  • https://prime.haskell.org/wiki/BangPatterns#Thebasicidea says

    A bang only really has an effect if it precedes a variable or wild-card pattern

    and

    putting a bang before a pattern that forces evaluation anyway does nothing

    and I think

    • rnf (D _) already forces evaluation anyway
      • because it's like rnf x = case x of D _ -> ...
    • so rnf !(D _) would have the same effect as rnf (D _)
    • and thus by substitution rnf !(D !_) must have the same effect as rnf (D !_)

So I think no, these two are always equivalent, but I'm asking anyway to have one super clear answer to refer people to.


回答1:


Indeed this is correct. We can see what is evaluated using :sprint in GHCi, which shows us what thunks have been evaluated.

With no bang patterns:

λ data D = D Int
λ d1 = D 1
λ :sprint d1
d1 = _
λ f1 (D _) = 0
λ f1 d1
0
λ :sprint d1
d1 = <D> _ -- Only D evaluated

With an inner bang pattern:

λ d2 = D 2
λ :sprint d2
d2 = _
λ f2 (D !_) = 0
λ f2 d2
0
λ :sprint d2
d2 = <D> 2 -- Everything evaluated

With an outer bang pattern:

λ d3 = D 3
λ :sprint d3
d3 = _
λ f3 !(D _) = 0
λ f3 d3
0
λ :sprint d3
d3 = <D> _ -- Only D evaluated

With an inner and outer bang patterns:

λ d4 = D 4
λ :sprint d4
d4 = _
λ f4 !(D !_) = 0
λ f4 d4
0
λ :sprint d4
d4 = <D> 4 -- Everything evaluated

From this we can easily see that the patterns !(D !_) and (D !_) are equivalent, and moreover that patterns of the form !(D ...) are redundant.



来源:https://stackoverflow.com/questions/53841764/do-inner-bang-patterns-always-force-outer-constructors-in-haskell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!