Question about BangPatterns semantics/documentation

The GHC User's Guide[1] says: | There is one (apparent) exception to this general rule that a bang | only makes a difference when it precedes a variable or wild-card: a | bang at the top level of a let or where binding makes the binding | strict, regardless of the pattern. (We say "apparent" exception | because the Right Way to think of it is that the bang at the top of a | binding is not part of the pattern; rather it is part of the syntax of | the binding, creating a "bang-pattern binding".) For example: | | let ![x,y] = e in b | | is a bang-pattern binding. Operationally, it behaves just like a case | expression: | | case e of [x,y] -> b However, the following two functions are not equivalent after compilation to Core: g, h :: (Int -> Int) -> Int -> () g f x = let !y = f x in () h f x = case f x of y -> () In fact, compilation results in g = \ (f_asi :: Int -> Int) (x_asj :: Int) -> case f_asi x_asj of _ [Occ=Dead] { I# ipv_sKS -> () } h = \ _ [Occ=Dead] _ [Occ=Dead] -> () Is the documentation inaccurate/incomplete/I-missed-something or is the implementation to blame? Cheers, hvr [1]: http://www.haskell.org/ghc/docs/7.8.3/html/users_guide/bang-patterns.html

Hi Herbert, Am Sonntag, den 03.08.2014, 11:31 +0200 schrieb Herbert Valerio Riedel:
However, the following two functions are not equivalent after compilation to Core:
g, h :: (Int -> Int) -> Int -> () g f x = let !y = f x in () h f x = case f x of y -> ()
In fact, compilation results in
g = \ (f_asi :: Int -> Int) (x_asj :: Int) -> case f_asi x_asj of _ [Occ=Dead] { I# ipv_sKS -> () }
h = \ _ [Occ=Dead] _ [Occ=Dead] -> ()
Is the documentation inaccurate/incomplete/I-missed-something or is the implementation to blame?
I think that in Haskell (which is not Core!), a "case" does not imply evaluation – only if the patterns require it. So the example in the docs is correct (case e of [x,y] -> b requires evaluation of e), but your example is simply optimized away. haskell.org is down, so I can’t check if the report has anything to say about that. Greetings, Joachim -- Joachim “nomeata” Breitner mail@joachim-breitner.de • http://www.joachim-breitner.de/ Jabber: nomeata@joachim-breitner.de • GPG-Key: 0xF0FBF51F Debian Developer: nomeata@debian.org

Yes, Joachim is dead right. In Haskell (case f x of y -> blah) really is equivalent to (let y = f x in blah). Herbert, if you think a reminder of this point, in the documentation or user manual, would be helpful, please suggest what and where. Simon | -----Original Message----- | From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of | Joachim Breitner | Sent: 03 August 2014 15:41 | To: ghc-devs@haskell.org | Subject: Re: Question about BangPatterns semantics/documentation | | Hi Herbert, | | Am Sonntag, den 03.08.2014, 11:31 +0200 schrieb Herbert Valerio Riedel: | > However, the following two functions are not equivalent after | > compilation to Core: | > | > g, h :: (Int -> Int) -> Int -> () | > g f x = let !y = f x in () | > h f x = case f x of y -> () | > | > In fact, compilation results in | > | > g = \ (f_asi :: Int -> Int) | > (x_asj :: Int) -> | > case f_asi x_asj of _ [Occ=Dead] { I# ipv_sKS -> () } | > | > h = \ _ [Occ=Dead] _ [Occ=Dead] -> () | > | > Is the documentation inaccurate/incomplete/I-missed-something or is | > the implementation to blame? | | I think that in Haskell (which is not Core!), a "case" does not imply | evaluation – only if the patterns require it. So the example in the | docs is correct (case e of [x,y] -> b requires evaluation of e), but | your example is simply optimized away. | | haskell.org is down, so I can’t check if the report has anything to say | about that. | | Greetings, | Joachim | | -- | Joachim “nomeata” Breitner | mail@joachim-breitner.de • http://www.joachim-breitner.de/ | Jabber: nomeata@joachim-breitner.de • GPG-Key: 0xF0FBF51F | Debian Developer: nomeata@debian.org
participants (3)
-
Herbert Valerio Riedel
-
Joachim Breitner
-
Simon Peyton Jones