diff options
author | Dr. ERDI Gergo <gergo@erdi.hu> | 2014-01-13 20:12:34 +0800 |
---|---|---|
committer | Austin Seipp <austin@well-typed.com> | 2014-01-20 11:30:22 -0600 |
commit | 4f8369bf47d27b11415db251e816ef1a2e1eb3d8 (patch) | |
tree | 61437b3b947951aace16f66379c462f2374fc709 /compiler/rename/RnPat.lhs | |
parent | 59cb44a3ee4b25fce6dc19816e9647e92e5ff743 (diff) | |
download | haskell-4f8369bf47d27b11415db251e816ef1a2e1eb3d8.tar.gz |
Implement pattern synonyms
This patch implements Pattern Synonyms (enabled by -XPatternSynonyms),
allowing y ou to assign names to a pattern and abstract over it.
The rundown is this:
* Named patterns are introduced by the new 'pattern' keyword, and can
be either *unidirectional* or *bidirectional*. A unidirectional
pattern is, in the simplest sense, simply an 'alias' for a pattern,
where the LHS may mention variables to occur in the RHS. A
bidirectional pattern synonym occurs when a pattern may also be used
in expression context.
* Unidirectional patterns are declared like thus:
pattern P x <- x:_
The synonym 'P' may only occur in a pattern context:
foo :: [Int] -> Maybe Int
foo (P x) = Just x
foo _ = Nothing
* Bidirectional patterns are declared like thus:
pattern P x y = [x, y]
Here, P may not only occur as a pattern, but also as an expression
when given values for 'x' and 'y', i.e.
bar :: Int -> [Int]
bar x = P x 10
* Patterns can't yet have their own type signatures; signatures are inferred.
* Pattern synonyms may not be recursive, c.f. type synonyms.
* Pattern synonyms are also exported/imported using the 'pattern'
keyword in an import/export decl, i.e.
module Foo (pattern Bar) where ...
Note that pattern synonyms share the namespace of constructors, so
this disambiguation is required as a there may also be a 'Bar'
type in scope as well as the 'Bar' pattern.
* The semantics of a pattern synonym differ slightly from a typical
pattern: when using a synonym, the pattern itself is matched,
followed by all the arguments. This means that the strictness
differs slightly:
pattern P x y <- [x, y]
f (P True True) = True
f _ = False
g [True, True] = True
g _ = False
In the example, while `g (False:undefined)` evaluates to False,
`f (False:undefined)` results in undefined as both `x` and `y`
arguments are matched to `True`.
For more information, see the wiki:
https://ghc.haskell.org/trac/ghc/wiki/PatternSynonyms
https://ghc.haskell.org/trac/ghc/wiki/PatternSynonyms/Implementation
Reviewed-by: Simon Peyton Jones <simonpj@microsoft.com>
Signed-off-by: Austin Seipp <austin@well-typed.com>
Diffstat (limited to 'compiler/rename/RnPat.lhs')
-rw-r--r-- | compiler/rename/RnPat.lhs | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/compiler/rename/RnPat.lhs b/compiler/rename/RnPat.lhs index fc62ed24d5..639ab51101 100644 --- a/compiler/rename/RnPat.lhs +++ b/compiler/rename/RnPat.lhs @@ -52,6 +52,7 @@ import RnTypes import DynFlags import PrelNames import TyCon ( tyConName ) +import ConLike import DataCon ( dataConTyCon ) import TypeRep ( TyThing(..) ) import Name @@ -135,13 +136,14 @@ wrapSrcSpanCps fn (L loc a) lookupConCps :: Located RdrName -> CpsRn (Located Name) lookupConCps con_rdr = CpsRn (\k -> do { con_name <- lookupLocatedOccRn con_rdr - ; k con_name }) - -- We do not add the constructor name to the free vars - -- See Note [Patterns are not uses] + ; (r, fvs) <- k con_name + ; return (r, addOneFV fvs (unLoc con_name)) }) + -- We add the constructor name to the free vars + -- See Note [Patterns are uses] \end{code} -Note [Patterns are not uses] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Note [Patterns are uses] +~~~~~~~~~~~~~~~~~~~~~~~~ Consider module Foo( f, g ) where data T = T1 | T2 @@ -154,6 +156,18 @@ Consider Arguaby we should report T2 as unused, even though it appears in a pattern, because it never occurs in a constructed position. See Trac #7336. +However, implementing this in the face of pattern synonyms would be +less straightforward, since given two pattern synonyms + + pattern P1 <- P2 + pattern P2 <- () + +we need to observe the dependency between P1 and P2 so that type +checking can be done in the correct order (just like for value +bindings). Dependencies between bindings is analyzed in the renamer, +where we don't know yet whether P2 is a constructor or a pattern +synonym. So for now, we do report conid occurances in patterns as +uses. %********************************************************* %* * @@ -603,7 +617,7 @@ rnHsRecFields1 ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot } -- That is, the parent of the data constructor. -- That's the parent to use for looking up record fields. find_tycon env con - | Just (ADataCon dc) <- wiredInNameTyThing_maybe con + | Just (AConLike (RealDataCon dc)) <- wiredInNameTyThing_maybe con = tyConName (dataConTyCon dc) -- Special case for [], which is built-in syntax -- and not in the GlobalRdrEnv (Trac #8448) | [GRE { gre_par = ParentIs p }] <- lookupGRE_Name env con |