|Version 1 (modified by 3 years ago) (diff),|
After parsing, and during renaming, pattern synonyms are stored as
The typechecking pass turns
PatSynDecls into a
PatSyn and several
HsBinds. To fill in the
PatSyn, we typecheck the right-hand side
of the pattern synonym declaration, then do some extra processing on
it to reject as-patterns and optionally compute the reverse of the
pattern synonym (for implicitly bidirectional ones). Afterwards, we
collect universal & existential type variables and typeclass dictionary
variables to be used when creating
ConPatOut patterns from pattern
synonym occurances, and generate some
PatSynstores typing information for the pattern synonym, to be consulted when typechecking pattern synonym usage sites.
- The first
HsBindis the binder for the matcher function generated from the pattern synonym. The matcher is used when desugaring pattern synonym usage sites (see below).
- For bidirectional pattern synonyms, another
HsBindcalled a wrapper is created to be used for pattern synonym usages in expression contexts. It is a wrapper in the same sense as a constructor wrapper.
Pattern synonym occurances in patterns are turned into
just like regular constructor matches.
ConPatOut has been changed to
ConLike instead of a
ConLike type is simply
the sum of
ConLikes are handled uniformly all the way until
mkCoAlgCaseMatchResult. There, we have a mixed list of
This list is grouped so that subsequent
DataCon patterns are put in
the same group, and
PatSyn patterns are all in their own
groups. This is needed so that when doing pattern matching per column,
data T = MkT1 | MkT2 Bool | MkT3 pattern P x = MkT2 x
and a list of cases
MkT1 _ -> alt1 P True -> alt2 MkT2 _ -> alt3
we don't compile that into
DEFAULT -> ... P ... MkT1 -> alt1 MkT2 _ -> alt3
since we can't see into P (and we don't want to, since it might be imported from another module). The correct thing to do is to compile that into
DEFAULT -> ... (P, alt2) and (MkT2 _, alt3) ... MkT1 -> alt1
Consecutive occurances of the same pattern synonym (e.g. if we had `P
and P False` in the previous example) are compiled into a
single match; the arguments are then matched in a sub-case.
For each pattern synonym, a matcher function is generated which gets a scrutinee and a success and a failure continuations. Given a type
data T a where MkT :: (Cls b) => b -> a -> T a
and a pattern synonym
pattern P x y = MkT x y
we generate the matcher function
P :: forall r a. T a -> (forall b. Cls b => b -> a -> r) -> r -> r P scrutinee pass fail = case scrutinee of MkT x y -> pass x y _ -> fail
Occurances of pattern synonyms are then desugared into calls to this matcher function. This allows pattern synonym definitions to be just as opaque as function definitions: their type defines their interface completely. This gives us a story for exporting pattern synonym definitions that is entirely consistent with existing function definition exports.