Implement pattern synonyms
authorDr. ERDI Gergo <gergo@erdi.hu>
Mon, 13 Jan 2014 12:12:34 +0000 (20:12 +0800)
committerAustin Seipp <austin@well-typed.com>
Mon, 20 Jan 2014 17:30:22 +0000 (11:30 -0600)
commit4f8369bf47d27b11415db251e816ef1a2e1eb3d8
tree61437b3b947951aace16f66379c462f2374fc709
parent59cb44a3ee4b25fce6dc19816e9647e92e5ff743
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>
99 files changed:
compiler/basicTypes/BasicTypes.lhs
compiler/basicTypes/ConLike.lhs [new file with mode: 0644]
compiler/basicTypes/DataCon.lhs-boot
compiler/basicTypes/OccName.lhs
compiler/basicTypes/PatSyn.lhs [new file with mode: 0644]
compiler/basicTypes/PatSyn.lhs-boot [new file with mode: 0644]
compiler/deSugar/Check.lhs
compiler/deSugar/Coverage.lhs
compiler/deSugar/Desugar.lhs
compiler/deSugar/DsBinds.lhs
compiler/deSugar/DsExpr.lhs
compiler/deSugar/DsMeta.hs
compiler/deSugar/DsMonad.lhs
compiler/deSugar/DsUtils.lhs
compiler/deSugar/Match.lhs
compiler/deSugar/MatchCon.lhs
compiler/ghc.cabal.in
compiler/ghc.mk
compiler/hsSyn/Convert.lhs
compiler/hsSyn/HsBinds.lhs
compiler/hsSyn/HsExpr.lhs
compiler/hsSyn/HsPat.lhs
compiler/hsSyn/HsPat.lhs-boot
compiler/hsSyn/HsTypes.lhs
compiler/hsSyn/HsUtils.lhs
compiler/iface/BinIface.hs
compiler/iface/BuildTyCl.lhs
compiler/iface/IfaceSyn.lhs
compiler/iface/MkIface.lhs
compiler/iface/TcIface.lhs
compiler/main/DynFlags.hs
compiler/main/HscMain.hs
compiler/main/HscStats.hs
compiler/main/HscTypes.lhs
compiler/main/PprTyThing.hs
compiler/main/TidyPgm.lhs
compiler/parser/Lexer.x
compiler/parser/Parser.y.pp
compiler/parser/RdrHsSyn.lhs
compiler/prelude/TysWiredIn.lhs
compiler/rename/RnBinds.lhs
compiler/rename/RnEnv.lhs
compiler/rename/RnNames.lhs
compiler/rename/RnPat.lhs
compiler/rename/RnSource.lhs
compiler/typecheck/TcBinds.lhs
compiler/typecheck/TcClassDcl.lhs
compiler/typecheck/TcDeriv.lhs
compiler/typecheck/TcEnv.lhs
compiler/typecheck/TcExpr.lhs
compiler/typecheck/TcForeign.lhs
compiler/typecheck/TcGenDeriv.lhs
compiler/typecheck/TcGenGenerics.lhs
compiler/typecheck/TcHsSyn.lhs
compiler/typecheck/TcHsType.lhs
compiler/typecheck/TcInstDcls.lhs
compiler/typecheck/TcPat.lhs
compiler/typecheck/TcPatSyn.lhs [new file with mode: 0644]
compiler/typecheck/TcPatSyn.lhs-boot [new file with mode: 0644]
compiler/typecheck/TcRnDriver.lhs
compiler/typecheck/TcRnMonad.lhs
compiler/typecheck/TcRnTypes.lhs
compiler/typecheck/TcSplice.lhs
compiler/typecheck/TcTyClsDecls.lhs
compiler/types/TypeRep.lhs
compiler/utils/UniqFM.lhs
compiler/utils/UniqSet.lhs
ghc/GhciTags.hs
testsuite/tests/driver/T4437.hs
testsuite/tests/ghc-api/T6145.hs
testsuite/tests/patsyn/Makefile [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/.gitignore [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/Makefile [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/all.T [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/bidir.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/ex-num.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/ex-prov.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/ex-view.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/ex.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/incomplete.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/num.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/overlap.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_compile/univ.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_fail/Makefile [new file with mode: 0644]
testsuite/tests/patsyn/should_fail/all.T [new file with mode: 0644]
testsuite/tests/patsyn/should_fail/mono.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_fail/mono.stderr [new file with mode: 0644]
testsuite/tests/patsyn/should_fail/unidir.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_fail/unidir.stderr [new file with mode: 0644]
testsuite/tests/patsyn/should_run/.gitignore [new file with mode: 0644]
testsuite/tests/patsyn/should_run/Makefile [new file with mode: 0644]
testsuite/tests/patsyn/should_run/all.T [new file with mode: 0644]
testsuite/tests/patsyn/should_run/eval.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_run/eval.stdout [new file with mode: 0644]
testsuite/tests/patsyn/should_run/ex-prov-run.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_run/ex-prov-run.stdout [new file with mode: 0644]
testsuite/tests/patsyn/should_run/match.hs [new file with mode: 0644]
testsuite/tests/patsyn/should_run/match.stdout [new file with mode: 0644]
utils/ghctags/Main.hs