[GHC] #8582: Record syntax for pattern synonyms

GHC ghc-devs at haskell.org
Fri Dec 4 01:12:31 UTC 2015


#8582: Record syntax for pattern synonyms
-------------------------------------+-------------------------------------
        Reporter:  cactus            |                Owner:  mpickering
            Type:  feature request   |               Status:  closed
        Priority:  high              |            Milestone:  8.0.1
       Component:  Compiler          |              Version:
      Resolution:  fixed             |             Keywords:
                                     |  PatternSynonyms
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:  5144              |             Blocking:
 Related Tickets:                    |  Differential Rev(s):  Phab:D1152
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by thomie):

 commit 2a74a64e8329ab9e0c74bec47198cb492d25affb:
 {{{
 Author: Matthew Pickering <matthewtpickering at gmail.com>
 Date:   Mon Oct 19 21:17:29 2015 +0100

     Record pattern synonyms

     This patch implements an extension to pattern synonyms which allows
 user
     to specify pattern synonyms using record syntax. Doing so generates
     appropriate selectors and update functions.

     === Interaction with Duplicate Record Fields ===

     The implementation given here isn't quite as general as it could be
 with
     respect to the recently-introduced `DuplicateRecordFields` extension.

     Consider the following module:

         {-# LANGUAGE DuplicateRecordFields #-}
         {-# LANGUAGE PatternSynonyms #-}

         module Main where

         pattern S{a, b} = (a, b)
         pattern T{a}    = Just a

         main = do
           print S{ a = "fst", b = "snd" }
           print T{ a = "a" }

     In principle, this ought to work, because there is no ambiguity. But
 at
     the moment it leads to a "multiple declarations of a" error. The
 problem
     is that pattern synonym record selectors don't do the same name
 mangling
     as normal datatypes when DuplicateRecordFields is enabled. They could,
     but this would require some work to track the field label and selector
     name separately.

     In particular, we currently represent datatype selectors in the third
     component of AvailTC, but pattern synonym selectors are just
 represented
     as Avails (because they don't have a corresponding type constructor).
     Moreover, the GlobalRdrElt for a selector currently requires it to
 have
     a parent tycon.

     (example due to Adam Gundry)

     === Updating Explicitly Bidirectional Pattern Synonyms ===

     Consider the following

     ```
     pattern Silly{a} <- [a] where
       Silly a = [a, a]

     f1 = a [5] -- 5

     f2 = [5] {a = 6} -- currently [6,6]
     ```

     === Fixing Polymorphic Updates ===

     They were fixed by adding these two lines in `dsExpr`. This might
 break
     record updates but will be easy to fix.

     ```
     + ; let req_wrap = mkWpTyApps (mkTyVarTys univ_tvs)

     - , pat_wrap = idHsWrapper }
     +, pat_wrap = req_wrap }
     ```

     === Mixed selectors error ===

     Note [Mixed Record Field Updates]
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

     Consider the following pattern synonym.

         data MyRec = MyRec { foo :: Int, qux :: String }

         pattern HisRec{f1, f2} = MyRec{foo = f1, qux=f2}

     This allows updates such as the following

         updater :: MyRec -> MyRec
         updater a = a {f1 = 1 }

     It would also make sense to allow the following update (which we
     reject).

         updater a = a {f1 = 1, qux = "two" } ==? MyRec 1 "two"

     This leads to confusing behaviour when the selectors in fact refer the
     same field.

         updater a = a {f1 = 1, foo = 2} ==? ???

     For this reason, we reject a mixture of pattern synonym and normal
     record selectors in the same update block. Although of course we still
     allow the following.

         updater a = (a {f1 = 1}) {foo = 2}

         > updater (MyRec 0 "str")
         MyRec 2 "str"
 }}}

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8582#comment:17>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list