Changes between Version 22 and Version 23 of Records/DeclaredOverloadedRecordFields


Ignore:
Timestamp:
Mar 8, 2012 7:43:58 AM (2 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):