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