Changes between Version 22 and Version 23 of Records/DeclaredOverloadedRecordFields
- Timestamp:
- 03/07/12 23:43:58 (15 months ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Records/DeclaredOverloadedRecordFields
v22 v23 6 6 * Many record types can be declared in the same module to share the field name. 7 7 * The field name can be exported so that records in other modules can share it. 8 8 9 The export/import is under usual H98 namespace and module/qualification control, so that when exporting a record type: 9 10 * Some fields can be both read and updated; … … 11 12 * Some can be completely hidden. 12 13 13 This proposal introduces several new elements of syntax, all of which desugar to use well-established extensions to ghc. The approach has been pro ptotyped in ghc v 7.2.1. In particular: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: 14 15 * The field name overloading is implemented through usual class and instance mechanisms. 15 16 * Field selectors are ordinary functions named for the field (but overloaded rather than H98's monomorphic), so field selection is regular function application. … … 17 18 === Implementation: the `Has` class, and methods `get` and `set` === 18 19 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 datadeclaration, 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 20 Record 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 23 24 get Cust{ customer_id } _ = customer_id -- DisambiguateRecordFields style 24 25 set _ x Cust{ .. } = Cust{ customer_id = x, .. } -- RecordWildCards and NamedFieldPuns 25 26 26 myCust :: Customer 27 myCust :: Customer -- example record decl 28 ... myCust{ customer_id = 27 } -- polymorphic record update 27 29 ... (customer_id myCust) ... -- field selection is func apply 28 ... myCust { customer_id = 27 } -- polymorphic record update29 }}} 30 31 Note that the mechanismuses 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 33 Note that the''' `Has` mechanism''' uses a Proxy as the type 'peg' for a field (this is the wildcard argument to `get` and `set`): 32 34 * The Proxy must be declared once, and is then under regular name control. 33 35 * The field selector function also must be declared once, using the Proxy. 34 36 35 37 {{{ 38 -- fieldLabel customer_id :: r -> Int -- new declaration, desugars to Proxy and func 36 39 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 38 41 customer_id r = get r (undefined :: Proxy_customer_id) 39 42 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 == 46 57 47 58 Explained in 5 wiki pages (these proposals are linked but somewhat orthogonal):
