diff options
author | Péter Diviánszky <divipp@gmail.com> | 2016-04-07 11:57:23 +0200 |
---|---|---|
committer | Péter Diviánszky <divipp@gmail.com> | 2016-04-07 11:57:23 +0200 |
commit | 1fb8403f0c3f56ddcc61f467e47dd8722ac55293 (patch) | |
tree | ff2388df7262af73ccd0a565b4808b5324c3db6a /doc | |
parent | 685fbe269923cfc0202975505fffbdca0479a065 (diff) |
more documentation on pattern match compilation
Diffstat (limited to 'doc')
-rw-r--r-- | doc/guide.pandoc | 155 |
1 files changed, 114 insertions, 41 deletions
diff --git a/doc/guide.pandoc b/doc/guide.pandoc index 64774eba..4fba4fe0 100644 --- a/doc/guide.pandoc +++ b/doc/guide.pandoc | |||
@@ -320,61 +320,77 @@ Design decisions: | |||
320 | 320 | ||
321 | ### Pattern guard trees | 321 | ### Pattern guard trees |
322 | 322 | ||
323 | Pattern guard trees is the simplest data structure which is general enough to express all pattern match related syntactic structures. | 323 | Pattern guard trees is an intermediate representation to which all pattern match related syntactic structures are transformed. |
324 | 324 | ||
325 | First we give a syntax of pattern guards trees which is used only in this documentation: | 325 | Syntax of pattern guards trees (used only in this documentation): |
326 | 326 | ||
327 | ----------- -- -------------------------------------------------------- ----------------------- | 327 | ----------- -- ---------------------------------------------------------- ----------------------- |
328 | *guardtree* := *expression* **guard tree leaf** | 328 | *guardtree* := *expression* **rhs** |
329 | | *guardtree* `|` *guardtree* **alternative patterns** | 329 | | *guardtree* `|` *guardtree* **alternative patterns** |
330 | | *conname* (*parpat*)* `<-` *expression* `->` *guardtree* **pattern guard** | 330 | | `MatchFailure` |
331 | | `let` *bindings* `in` *guardtree* **let binding** | 331 | | *pattern* `<-` *expression* `,` *guardtree* **pattern guard** |
332 | *parpat* := *pattern* | 332 | | `let` *bindings* `in` *guardtree* **let binding** |
333 | | *parpat* `,` *parpat* **parallel patterns** | 333 | ----------- -- ---------------------------------------------------------- ----------------------- |
334 | *pattern* := *variable* **variable pattern** | ||
335 | | *conname* (*parpat*)* **constructor pattern** | ||
336 | | *expression* -> *parpat* **view pattern** | ||
337 | | *parpat* `::` *expression* **type annotation** | ||
338 | ----------- -- -------------------------------------------------------- ----------------------- | ||
339 | 334 | ||
340 | Remarks: | 335 | Remarks: |
341 | 336 | ||
342 | - A guard tree is an expression (it may appear whereever an expression may appear) | 337 | - Pattern guard trees are generalizations of [pattern guards](https://wiki.haskell.org/Pattern_guard): |
338 | - pattern guard trees are expressions (may appear whereever an expression may appear) | ||
339 | - pattern guard trees may have alternatives not only on the top level | ||
340 | For example, in `[] <- x, (Nothing <- y, ... | True <- z, ...)` both alternatives will match only if `x` is an empty list. | ||
341 | - pattern guard trees may have let bindings not only on the top level | ||
342 | - Pattern guard trees form a monoid with alternative patterns and `MatchFailure`. | ||
343 | 343 | ||
344 | Examples: | 344 | Examples: |
345 | 345 | ||
346 | 1. definition of `not` with pattern guard trees: | 346 | 1. Definition of `not` with pattern guard trees: |
347 | |||
348 | ~~~~~ {.haskell} | ||
349 | not x = (True <- x, False) | (False <- x, True) | ||
350 | ~~~~~ | ||
351 | |||
352 | 2. Definition of `zip`: | ||
353 | |||
354 | ~~~~~ {.haskell} | ||
355 | zip [] _ = [] | ||
356 | zip x [] = [] | ||
357 | zip (a:as) (b:bs) = (a,b) : zip as bs | ||
358 | ~~~~~ | ||
359 | |||
360 | A possible translation to pattern guard trees: | ||
347 | 361 | ||
348 | ~~~~~ {.haskell} | 362 | ~~~~~ {.haskell} |
349 | not x = (True <- x -> False) | (False <- x -> True) | 363 | zip v0 v1 |
364 | = ([] <- v0, []) | ||
365 | | (let x = v0 in [] <- v1, []) | ||
366 | | ((:) a as <- v0, (:) b bs <- v1, (a, b): zip as bs) | ||
350 | ~~~~~ | 367 | ~~~~~ |
351 | 368 | ||
352 | The semantics of pattern guard trees is given by the `value`, `matchesP` and `matches` functions (pseudo code): | 369 | #### Semantics |
370 | |||
371 | The semantics of pattern guard trees is given by the `value` function: | ||
372 | (This is pseudo code, it could be turned into a valid function producing a template Haskell splice): | ||
353 | 373 | ||
354 | ~~~~~ {.haskell} | 374 | ~~~~~ {.haskell} |
355 | value :: GuardTree a -> Maybe a | 375 | value :: GuardTree a -> Maybe a |
356 | value (Leaf e) = Just e | 376 | value (Leaf e) = Just e |
357 | value (Alt x y) = value x <> value y | 377 | value (Alt x y) = value x <|> value y |
358 | value (Let bs x) = value (let bs in x) | 378 | value MatchFailure = Nothing |
359 | value (PatternGuard cn ps e x) = case PCon cn ps `matches` e of | 379 | value (Let bs x) = value (let $bs in x) |
360 | Just bs -> value (let bs in x) | 380 | value (PatternGuard p e x) = case matchPattern p e of |
361 | Nothing -> Nothing | 381 | Just bs -> value (let $bs in x) |
362 | 382 | _ -> Nothing | |
363 | matchesP :: ParPat a -> a -> Maybe [Binding] | 383 | |
364 | Pat x `matchesP` v = x `matches' v | 384 | matchPattern :: Pattern a -> Expression a -> Maybe Bindings |
365 | ParPat x y `matchesP` v = case x `matchesP` v of | 385 | ... |
366 | Just bs -> case let bs in y `matchesP` v of | 386 | |
367 | Just bs' -> Just (bs ++ bs') | 387 | data GuardTree a where |
368 | Nothing -> Nothing | 388 | Leaf :: Expression a -> GuardTree a |
369 | Nothing -> Nothing | 389 | Alt :: GuardTree a -> GuardTree a -> GuardTree a |
370 | 390 | MatchFailure :: GuardTree a | |
371 | matches :: Pattern a -> a -> Maybe [Binding] | 391 | -- bindings are not strongly typed here for simplicity |
372 | Var n `matches` v = Just [n = v] | 392 | Let :: Bindings -> GuardTree a -> GuardTree a |
373 | PCon cn ps `matches` v = case v of | 393 | PatternGuard :: Pattern b -> Expression b -> GuardTree a -> GuardTree a |
374 | cn vs -> mconcat (sequence (zipWith matchesP ps vs)) | ||
375 | _ -> Nothing | ||
376 | ViewPat f p `matches` v = p `matches` f v | ||
377 | TypeAnn p t `matches` v = p `matches` v | ||
378 | ~~~~~ | 394 | ~~~~~ |
379 | 395 | ||
380 | 396 | ||
@@ -382,14 +398,71 @@ TypeAnn p t `matches` v = p `matches` v | |||
382 | 398 | ||
383 | #### Function alternatives | 399 | #### Function alternatives |
384 | 400 | ||
401 | 1. make n fresh variables v1, ..., vn where n is the arity of the function | ||
402 | 2. the new left hand side is `f` v1 ... vn | ||
403 | 3. translate each function alternative to a pattern guard tree with the help of v1, ..., vn | ||
404 | 4. compose the pattern guard trees with alternative patterns to get the new right hand side | ||
405 | |||
406 | Example: | ||
407 | |||
408 | ~~~~~ {.haskell} | ||
409 | zip [] _ = [] | ||
410 | zip x [] = [] | ||
411 | zip (a:as) (b:bs) = (a,b) : zip as bs | ||
412 | ~~~~~ | ||
413 | |||
414 | Transformed code: | ||
385 | 415 | ||
416 | ~~~~~ {.haskell} | ||
417 | zip v0 v1 | ||
418 | = ([] <- v0, _ <- v1, []) | ||
419 | | (x <- v0, [] <- v1, []) | ||
420 | | (a:as <- v0, b:bs <- v1, (a,b) : zip as bs) | ||
421 | ~~~~~ | ||
386 | 422 | ||
387 | 423 | ||
388 | #### View patterns | 424 | #### View patterns |
389 | 425 | ||
390 | 426 | ||
427 | ### Normalization of pattern guard trees | ||
428 | |||
429 | The normal form of pattern guard trees contains only simple constructor patterns: | ||
430 | |||
431 | ------------- -- ---------------------------------------------------------- ----------------------- | ||
432 | *conpattern* := *conname* (*variable*)* | ||
433 | ------------- -- ---------------------------------------------------------- ----------------------- | ||
434 | |||
435 | The normalization process is driven by the shape of patterns: | ||
436 | |||
437 | |||
438 | pattern shape input output | ||
439 | -------------- ---------------------------- -- -------- | ||
440 | wildcard `_` `<-` e `,` t ~> t | ||
441 | variable v `<-` e `,` t ~> `let` v = e `in` t | ||
442 | at-pattern v`@`p `<-` e `,` t ~> `let` v = e `in` p `<-` v `,` t | ||
443 | nested pattern C p1 ... pn `<-` e `,` t ~> C w1 ... wn `<-` e `,` p1 `<-` w1 `,` ... `,` pn `<-` wn `,` t | ||
444 | view pattern (f `->` p) `<-` e `,` t ~> p `<-` f e `,` t | ||
445 | -------------- ---------------------------- -- -------- | ||
446 | |||
447 | |||
391 | ### Compilation of pattern guard trees | 448 | ### Compilation of pattern guard trees |
392 | 449 | ||
450 | #### Filtering | ||
451 | |||
452 | Filtering is a transformation on pattern guard trees, given an expession and a constructor name: | ||
453 | |||
454 | ~~~~~ {.haskell} | ||
455 | filterTree :: Expression b -> Expression b -> GuardTree a -> GuardTree a | ||
456 | filterTree _ _ (Leaf e) = Leaf e | ||
457 | filterTree e a (Alt x y) = filterTree e a x <> filterTree e a y | ||
458 | filterTree e a MatchFailure = MatchFailure | ||
459 | filterTree e a (Let bs t) = Let bs (filterTree e a t) | ||
460 | filterTree e a@(Con c es) (PatternGuard (PCon c' vs) e' t) | ||
461 | | e /= e' = PatternGuard (PCon c' vs) e' (filterTree e a t) | ||
462 | | c /= c' = Nothing | ||
463 | | otherwise = filterTree e a (let $(bind vs es) t) | ||
464 | ~~~~~ | ||
465 | |||
393 | 466 | ||
394 | ### TODO | 467 | ### TODO |
395 | 468 | ||