Changes between Version 23 and Version 24 of Records/DeclaredOverloadedRecordFields
- Timestamp:
- 03/08/12 00:23:03 (15 months ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Records/DeclaredOverloadedRecordFields
v23 v24 4 4 5 5 This 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. 8 9 9 10 The export/import is under usual H98 namespace and module/qualification control, so that when exporting a record type: … … 12 13 * Some can be completely hidden. 13 14 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: 15 In case of 'unintended' clash (another module using the same name 'by accident'), usual H98 controls apply to protect encapsulation and representation hiding. 16 17 This 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: 15 18 * 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.) 17 20 18 21 === Implementation: the `Has` class, and methods `get` and `set` === 19 22 20 Record declarations generate a `Has` instance for each record type/field combination. Example declaration, its `Has` instance, and examples of use: 21 {{{ 23 Record 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 22 29 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 24 31 get Cust{ customer_id } _ = customer_id -- DisambiguateRecordFields style 25 32 set _ x Cust{ .. } = Cust{ customer_id = x, .. } -- RecordWildCards and NamedFieldPuns 26 33 27 myCust :: Customer -- examplerecord decl34 myCust :: Customer -- usual record decl 28 35 ... myCust{ customer_id = 27 } -- polymorphic record update 29 36 ... (customer_id myCust) ... -- field selection is func apply … … 44 51 }}} 45 52 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 . 55 71 56 72 == DORF Full motivation and examples == … … 60 76 * ''' [wiki:Records/DeclaredOverloadedRecordFields/NoMonoRecordFields No Mono Record Fields] ''' (precursor to DORF) 61 77 * ''' DORF -- Application Programmer's view ''' (this page) 62 * ''' [wiki:Records/DeclaredOverloadedRecordFields/ImplementorsView DORF -- Implement or's view] '''78 * ''' [wiki:Records/DeclaredOverloadedRecordFields/ImplementorsView DORF -- Implementer's view] ''' 63 79 * ''' [wiki:Records/DeclaredOverloadedRecordFields/COmpareSORF DORF -- Comparison to SORF (and TDNR)] ''' 64 80 * ''' [wiki:Records/DeclaredOverloadedRecordFields/DotPostfix Dot as Postfix Function Apply] ''' ('''''optional''''' syntactic sugar)
