| 176 | | === Tricky point: nested bangs === |
| | 176 | Another point that came up in implementation is this. In GHC, at least, |
| | 177 | ''patterns'' are initially parsed as ''expressions'', because Haskell's syntax |
| | 178 | doesn't let you tell the two apart until quite late in the day. |
| | 179 | In expressions, the form {{{(! x)}}} is a right section, and parses fine. |
| | 180 | But the form {{{(!x, !y)}}} is simply illegal. Solution: |
| | 181 | in the syntax of expressions, allow sections without the wrapping parens |
| | 182 | in explicit lists and tuples. Actually this would make sense generally: |
| | 183 | what could {{{(+ 3, + 4)}}} mean apart from a tuple of two sections? |
| | 184 | |
| | 185 | == Tricky point: nested bangs == |
| | 199 | This means that you can't give the obvious alternative translation that uses |
| | 200 | just let-bindings and {{{seq}}. For example, we could attempt to translate |
| | 201 | the example to: |
| | 202 | {{{ |
| | 203 | let |
| | 204 | t = <rhs> |
| | 205 | x = case t of (x, Just !y) -> x |
| | 206 | y = case t of (x, Just !y) -> y |
| | 207 | in |
| | 208 | t `seq` <body> |
| | 209 | }}} |
| | 210 | This won't work, because using `seq` on `t` won't force `y`. |
| | 211 | You could build an intermediate tuple, thus: |
| | 212 | {{{ |
| | 213 | let |
| | 214 | t = case <rhs> of (x, Just !y) -> (x,y) |
| | 215 | x = fst t |
| | 216 | y = snd t |
| | 217 | in |
| | 218 | t `seq` <body> |
| | 219 | }}} |
| | 220 | But that seems a waste when the patttern is itself just a tuple; |
| | 221 | and it needs adjustment when there is only one bound variable. |
| | 222 | |
| | 223 | Bottom line: for non-recursive bindings, the straightforward translation |
| | 224 | to a `case` is, well, straightforward. Recursive bindings could probably |
| | 225 | be handled, but it's more complicated. |
| | 226 | |
| | 227 | == Tricky point: pattern-matching semantics == |
| | 228 | |
| | 229 | A bang is part of a ''pattern''; matching a bang forces evaluation. |
| | 230 | So the exact placement of bangs in equations matters. For example, |
| | 231 | there is a difference between these two functions: |
| | 232 | {{{ |
| | 233 | f1 x True = True |
| | 234 | f1 !x False = False |
| | 235 | |
| | 236 | f2 !x True = True |
| | 237 | f2 x False = False |
| | 238 | }}} |
| | 239 | Since pattern matching goes top-to-bottom, left-to-right, |
| | 240 | {{{(f1 bottom True)}}} is {{{True}}}, whereas {{{(f2 bottom True)}}} |
| | 241 | is {{{bottom}}}. |
| | 242 | |
| | 259 | One could say that the translation isn't required to preserve the static |
| | 260 | semantics, but GHC, at least, translates into System F, and being able |
| | 261 | to do so is a good sanity check. If we were to do that, then we would |
| | 262 | need |
| | 263 | {{{ |
| | 264 | <rhs> :: Maybe (forall a. Num a => a -> a) |
| | 265 | }}} |
| | 266 | so that the case expression works out in System F: |
| | 267 | {{{ |
| | 268 | case <rhs> of { |
| | 269 | Just (f :: forall a. Num a -> a -> a) |
| | 270 | -> (f Int dNumInt (1::Int), f Integer dNumInteger (2::Integer) } |
| | 271 | }}} |
| | 272 | The trouble is that `<rhs>` probably has a type more like |
| | 273 | {{{ |
| | 274 | <rhs> :: forall a. Num a => Maybe (a -> a) |
| | 275 | }}} |
| | 276 | ...and now the dictionary lambda may get in the way |
| | 277 | of forcing the pattern. |
| | 278 | |
| | 279 | This is a swamp. '''Conservative conclusion''': no generalisation (at all) |
| | 280 | for bang-pattern bindings. |