Changes between Version 22 and Version 23 of Records/DeclaredOverloadedRecordFields


Ignore:
Timestamp:
Mar 8, 2012 7:43:58 AM (3 years ago)
Author:
AntC
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Records/DeclaredOverloadedRecordFields

    v22 v23  
    66 * Many record types can be declared in the same module to share the field name.
    77 * The field name can be exported so that records in other modules can share it.
     8
    89The export/import is under usual H98 namespace and module/qualification control, so that when exporting a record type:
    910 * Some fields can be both read and updated;
     
    1112 * Some can be completely hidden.
    1213
    13 This proposal introduces several new elements of syntax, all of which desugar to use well-established extensions to ghc. The approach has been proptotyped in ghc v 7.2.1. In particular:
     14This proposal introduces several new elements of syntax, all of which desugar to use well-established extensions to ghc. The approach has been prototyped in ghc v 7.2.1. In particular:
    1415 * The field name overloading is implemented through usual class and instance mechanisms.
    1516 * Field selectors are ordinary functions named for the field (but overloaded rather than H98's monomorphic), so field selection is regular function application.
     
    1718=== Implementation: the `Has` class, and methods `get` and `set` ===
    1819
    19 Record declarations, instead of generating a (monomorphic) selector function named for the field, generate a `Has` instance for each record type/field combination. A data declaration, its `Has` instance, and examples of use:
    20 {{{
    21     data Customer = Cust{ customer_id :: Int, ... }
    22     instance (t ~ Int) => Has Customer Proxy_customer_id t        where
     20Record declarations generate a `Has` instance for each record type/field combination. Example declaration, its `Has` instance, and examples of use:
     21{{{
     22    data Customer = Cust{ customer_id :: Int, ... }                     -- declaration syntax same as H98
     23    instance (t ~ Int) => Has Customer Proxy_customer_id t        where -- Has instance generated
    2324        get Cust{ customer_id } _ = customer_id                         -- DisambiguateRecordFields style
    2425        set _ x Cust{ .. }        = Cust{ customer_id = x, .. }         -- RecordWildCards and NamedFieldPuns
    2526
    26     myCust :: Customer
     27    myCust :: Customer                                                  -- example record decl
     28    ... myCust{ customer_id = 27 }                                      -- polymorphic record update
    2729    ... (customer_id myCust) ...                                        -- field selection is func apply
    28     ... myCust{ customer_id = 27 }                                      -- polymorphic record update
    29 }}}
    30 
    31 Note that the mechanism uses a Proxy as the type 'peg' for a field (this is the wildcard argument to `get` and `set`):
     30    ... myCust.customer_id ...                                          -- dot notation is sugar for reverse func apply
     31}}}
     32
     33Note that the''' `Has` mechanism''' uses a Proxy as the type 'peg' for a field (this is the wildcard argument to `get` and `set`):
    3234 * The Proxy must be declared once, and is then under regular name control.
    3335 * The field selector function also must be declared once, using the Proxy.
    3436
    3537{{{
     38    -- fieldLabel customer_id :: r -> Int                               -- new declaration, desugars to Proxy and func
    3639    data Proxy_customer_id                                              -- phantom
    37     customer_id :: r{ customer_id :: Int }
     40    customer_id :: r{ customer_id :: Int } => r -> Int                  -- r{ ... } is sugar for Has constraint
    3841    customer_id r = get r (undefined :: Proxy_customer_id)
    3942
    40     set Proxy_customer_id 27 myCust
    41 }}}
    42  * The field selector function is an (overloaded) call to the `get` function, it's type is a function from a record to
    43 
    44 
    45 
     43    set (undefined :: Proxy_customer_id) 27 myCust                      -- record update desugarred from above
     44}}}
     45
     46'''Virtual''' or '''pseudo-''' fields are easy to create, because field selection is merely function application. Virtual fields can be applied like ordinary fields (but can't be updated, because there is no `Has` instance):
     47{{{
     48    fullName r = r.firstName ++ " " ++ map toUpper r.lastName           -- example addapted from SPJ
     49                                                                        -- note dot notation binds tighter than func apply
     50    fullName :: r{ firstName :: String, lastName :: String} => r -> String     -- type inferred for fullName
     51}}}
     52
     53(Note the `Has` constraints for fullName using elided syntax.)
     54
     55
     56== DORF Full motivation and examples ==
    4657
    4758Explained in 5 wiki pages (these proposals are linked but somewhat orthogonal):