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)