46 | | `pattern` ''conid'' ''varid,,1,,'' ... ''varid,,n,,'' `=` ''patexp'' |
| 41 | `pattern` ''conid'' ''varid,,1,,'' ... ''varid,,n,,'' `=` ''pat'' |
48 | | where ''patexp'' is the intersection of the grammars for patterns and expression, i.e., those terms that are valid both as a pattern and as an expression. |
49 | | * Each of the variables on the left hand side must occur exactly once on the right hand side, and these are the only variables that can occur on the right hand side. |
| 43 | `pattern` ''varid,,1,,'' ''consym'' ''varid,,2,,'' `=` ''pat'' |
| 44 | |
| 45 | * Each of the variables on the left hand side must occur exactly once on the right hand side |
65 | | == Pattern only synonyms == |
66 | | Simple patterns synonyms are restricted to having a right hand side that is also a valid expression. |
67 | | Pattern only synonyms can have any pattern on the right hand side, but may only be used in patterns. |
68 | | |
69 | | `pattern` ''conid'' ''varid,,1,,'' ... ''varid,,n,,'' `=` ''pat'' |
70 | | |
71 | | Again, each of the variables on the left hand side must be mentioned exactly once on the right hand side, but now the right hand side can mention other variables as well. These variables will not be bound when using the pattern synonym. |
72 | | |
73 | | Examples: |
74 | | {{{ |
75 | | pattern ThirdElem x = _:_:x:_ |
76 | | pattern LazySecond a b = (a, ~b) |
77 | | |
78 | | third (ThirdElem a) = a |
79 | | third _ = error "No third" |
80 | | |
81 | | fcn :: (Int, (Int, Int)) |
82 | | fcn (LazySecond x (y, z)) = if x == 0 then 0 else y+z |
83 | | }}} |
84 | | And their expansions |
85 | | {{{ |
86 | | third (_:_:a:_) = a |
87 | | third _ = error "No third" |
88 | | |
89 | | fcn :: (Int, (Int, Int)) |
90 | | fcn (x, ~(y, z)) = if x == 0 then 0 else y+z |
91 | | }}} |
92 | | |
102 | | == Bidirectional pattern synonyms == |
| 83 | Another example showing pattern synonyms used as views, with regular ViewPatterns: |
| 84 | |
| 85 | {{{ |
| 86 | import qualified Data.Sequence as Seq |
| 87 | |
| 88 | pattern Empty = (Seq.viewl -> Seq.EmptyL) |
| 89 | pattern x :< xs = (Seq.viewl -> x Seq.:< xs) |
| 90 | pattern xs :> x = (Seq.viewr -> xs Seq.:> x) |
| 91 | }}} |
| 92 | |
| 93 | |
| 94 | |
| 95 | == Implicitly-bidirectional pattern synonyms == |
| 96 | |
| 97 | In cases where ''pat'' is in the intersection of the grammars for patterns and expressions (i.e. is valid both as an expression and a pattern), the pattern synonym is said to be bidirectional, and can be used in expression contexts as well. |
| 98 | |
| 99 | For example, the following two are not bidirectional: |
| 100 | |
| 101 | {{{ |
| 102 | pattern ThirdElem x = _:_:x:_ |
| 103 | pattern Snd y = (x, y) |
| 104 | }}} |
| 105 | |
| 106 | since the right-hand side is not a closed expression of {''x''} and {''y''} respectively. |
| 107 | |
| 108 | In contrast, the pattern synonyms for ''Arrow'' and ''Int'' above are bidirectional, so you can e.g. write: |
| 109 | |
| 110 | {{{ |
| 111 | arrows :: [Type] -> Type -> Type |
| 112 | arrows = flip $ foldr Arrow |
| 113 | }}} |
| 114 | |
| 115 | |
| 116 | == Explicitly-bidirectional pattern synonyms == |
| 117 | |