Changes between Version 2 and Version 3 of BangPatterns


Ignore:
Timestamp:
Feb 2, 2006 4:57:58 PM (9 years ago)
Author:
simonpj@…
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • BangPatterns

    v2 v3  
    6565== Non-recursive let and where bindings == 
    6666 
     67First, we deal with ''non-recursive'' bindings only. 
    6768In Haskell, let and where bindings can bind patterns.  Their semantics is given by translation to a case, with an implicit implicit tilde (~). 
    6869{{{ 
     
    9697which evaluates the (f x), thereby giving a strict `let`. 
    9798 
     99== Examples == 
    98100Here is a more realistic example, a strict version of partition: 
    99101{{{ 
     
    120122needed in this example but often useful). 
    121123 
     124== Top-level bang-pattern bindings == 
     125 
     126Does this make sense? 
     127{{{ 
     128  module Foo where 
     129    !x = factorial 1000 
     130}}} 
     131A top-level bang-pattern binding like this would imply that 
     132the binding is evaluated when the program is started; a kind of 
     133module initialisation.  This makes some kind of sense, since  
     134(unlike unrestricted side effects) it doesn't matter in which order 
     135the module initialisation is performed. 
     136 
     137But it's not clear why it would be necessary or useful.  Conservative 
     138conclusion: no top-level bang-patterns. 
     139 
     140== Recursive let and where bindings == 
     141 
     142It is just about possible to make sense of bang-patterns in  
     143''recursive'' let and where bindings.  At first you might think they 
     144don't make sense: how can you evaluate it strictly if it doesn't exist 
     145yet?  But consider 
     146{{{ 
     147  let !xs = if funny then 1:xs else 2:xs in ... 
     148}}} 
     149Here the binding is recursive, but makes sense to think of it 
     150as equivalent to 
     151{{{ 
     152  let xs = if funny then 1:xs else 2:xs  
     153  in xs `seq` ... 
     154}}} 
     155But (a) it must be unusual, and (b) I have found it very hard to 
     156come up with a plausible translation (that deals with all the tricky  
     157points).   
     158 
     159Conservative conclusion: bang-pattern bindings must be non-recursive. 
     160 
     161=== Tricky point: syntax === 
     162 
     163What does this mean? 
     164{{{ 
     165   f ! x = True 
     166}}} 
     167Is this a definition of `(!)` or a banged argument?   (Assuming that 
     168space is insignificant.) 
     169 
     170Proposal: resolve this ambiguity in favour of the bang-pattern. If 
     171you want to define `(!)`, use the prefix form 
     172{{{ 
     173   (!) f x = True 
     174}}} 
     175 
     176=== Tricky point: nested bangs === 
     177 
     178Consider this: 
     179{{{ 
     180  let !(x, Just !y) = <rhs> in <body> 
     181}}} 
     182This should be equivalent to 
     183{{{ 
     184  case <rhs> of { (x, Just !y) -> <body> } 
     185}}} 
     186Notice that this meant that the '''entire''' pattern is matched 
     187(as always with Haskell).  The `Just` may fail; `x` is  
     188not evaluated; but `y` '''is''' evaluated. 
     189 
     190== Tricky point: polymorphism == 
     191 
     192Haskell allows this: 
     193{{{ 
     194  let f :: forall a. Num a => a->a 
     195      Just f = <rhs> 
     196  in (f (1::Int), f (2::Integer)) 
     197}}} 
     198But if we were to allow a bang pattern, `!Just f = <rhs>`,  
     199with the translation to 
     200a case expression given earlier, we would end up with 
     201{{{ 
     202   case <rhs> of { Just f -> (f (1::Int), f (2::Integer) } 
     203}}} 
     204But if this is Haskell source, then `f` won't be polymorphic. 
     205 
     206 
    122207== Changes to the Report == 
    123208