Changes between Version 23 and Version 24 of Records/DeclaredOverloadedRecordFields


Ignore:
Timestamp:
Mar 8, 2012 8:23:03 AM (3 years ago)
Author:
AntC
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Records/DeclaredOverloadedRecordFields

    v23 v24  
    44
    55This proposal is addressing the narrow issue of '''namespacing for record field names''' by allowing more than one record in the same module to share a field name. Specifically the record field name is overloaded so that:
    6  * Many record types can be declared in the same module to share the field name.
    7  * The field name can be exported so that records in other modules can share it.
     6 * __Within the same module__, many record types can be declared to share the field name.
     7 * The field name can be exported so that records __in other modules__ can share it.
     8 * Furthermore, other modules __can create records__ using that field name, and share it.
    89
    910The export/import is under usual H98 namespace and module/qualification control, so that when exporting a record type:
     
    1213 * Some can be completely hidden.
    1314
    14 This 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:
     15In case of 'unintended' clash (another module using the same name 'by accident'), usual H98 controls apply to protect encapsulation and representation hiding.
     16
     17This proposal introduces several new elements of syntax, all of which desugar to use well-established extensions of ghc. The approach has been prototyped in ghc v 7.2.1. In particular:
    1518 * The field name overloading is implemented through usual class and instance mechanisms.
    16  * Field selectors are ordinary functions named for the field (but overloaded rather than H98's monomorphic), so field selection is regular function application.
     19 * Field selectors are ordinary functions named for the field (but overloaded rather than H98's monomorphic), so field selection is regular function application. (There is no need for syntactically-based disambiguation at point of use.)
    1720
    1821=== Implementation: the `Has` class, and methods `get` and `set` ===
    1922
    20 Record declarations generate a `Has` instance for each record type/field combination. Example declaration, its `Has` instance, and examples of use:
    21 {{{
     23Record declarations generate a `Has` instance for each record type/field combination. As well as type arguments for the record and field, there is a third argument for the field's type, which is set at the instance level using equality constraints in a functional-dependencies style. Here is the `Has` class (`r` is the record, `fld` is the proxy type for the field, `t` is the fields type), an example declaration, its `Has` instance, and examples of use:
     24{{{
     25    class Has r fld t                                             where
     26        get :: r -> fld -> t                                            -- simplified form
     27        set :: fld -> t -> r -> r                                       -- where not changing record's type
     28
    2229    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
     30    instance (t ~ Int) => Has Customer Proxy_customer_id t        where -- Has instance generated, with ~ constraint
    2431        get Cust{ customer_id } _ = customer_id                         -- DisambiguateRecordFields style
    2532        set _ x Cust{ .. }        = Cust{ customer_id = x, .. }         -- RecordWildCards and NamedFieldPuns
    2633
    27     myCust :: Customer                                                  -- example record decl
     34    myCust :: Customer                                                  -- usual record decl
    2835    ... myCust{ customer_id = 27 }                                      -- polymorphic record update
    2936    ... (customer_id myCust) ...                                        -- field selection is func apply
     
    4451}}}
    4552
    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 
     53'''Virtual''' or '''pseudo-''' fields are easy to create and use, because field selection is merely function application. Virtual fields look like ordinary fields (but can't be updated, because there is no `Has` instance):
     54{{{
     55    fullName r = r.firstName ++ " " ++ map toUpper r.lastName           -- example adapted from SPJ
     56                                                                        -- dot notation binds tighter than func apply
     57    fullName :: r{ firstName :: String, lastName :: String} => r -> String
     58                                                                        -- type inferred for fullName
     59                                                                        -- the Has constraints use elided syntax
     60}}}
     61
     62'''Technical capabilities''' and limitations for the `Has` class:
     63 * Monomorphic fields can be `get` and `set`.
     64 * Parametric polymorphic fields can be applied in polymorphic contexts, and can be `set` including changing the type of the record.
     65 * Higher-ranked polymorphic fields can be applied in polymorphic contexts, but cannot be set.[[BR]]Uses equality constraints on the instance to 'improve' types.
     66 * `Has` uses type family functions to manage type-changing update, which adds complexity -- see Implementer's view.
     67 * Multiple fields can be updated in a single expression (using familiar H98 syntax), but this desugars to nested updates, which is inefficient.
     68 * Pattern matching and record creation using data constructor prefix to { ... } work as per H98 (using DisambiguateRecordFields and friends).
     69
     70.
    5571
    5672== DORF Full motivation and examples ==
     
    6076 * ''' [wiki:Records/DeclaredOverloadedRecordFields/NoMonoRecordFields No Mono Record Fields] '''   (precursor to DORF)
    6177 * ''' DORF -- Application Programmer's view '''     (this page)
    62  * ''' [wiki:Records/DeclaredOverloadedRecordFields/ImplementorsView DORF -- Implementor's view] '''
     78 * ''' [wiki:Records/DeclaredOverloadedRecordFields/ImplementorsView DORF -- Implementer's view] '''
    6379 * ''' [wiki:Records/DeclaredOverloadedRecordFields/COmpareSORF DORF -- Comparison to SORF (and TDNR)] '''
    6480 * ''' [wiki:Records/DeclaredOverloadedRecordFields/DotPostfix Dot as Postfix Function Apply] '''   ('''''optional''''' syntactic sugar)