Changes between Version 4 and Version 5 of Records/TypePunningDeclaredOverloadedRecordFields


Ignore:
Timestamp:
Mar 12, 2012 3:44:35 AM (3 years ago)
Author:
AntC
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Records/TypePunningDeclaredOverloadedRecordFields

    v4 v5  
    2525Note that SORF introduces a third argument for the field's resulting type. (This is specifically to support higher-rank typed fields; but despite the complexity it introduces, SORF has no mechanism to __update__ h-r fields.) 
    2626 
    27 TPDORF approaches h-r fields in a different way, which supports __both__ setting and getting those fields. (I'm not claiming this is a ''solution'', more a well-principled work-round. And not a hack.) 
     27TPDORF approaches h-r fields in a different way, which supports __both__ setting and getting those fields. (I'm not claiming this is a ''solution'', more a well-principled work-round. And not a hack. It is both scalable, and supports class-constrained higher-rank types.) 
    2828 
    2929'''The main insight''' is that to manage large-scale data models (in which namespacing becomes onerous, and name sharing would be most beneficial), there are typically strong naming conventions and representation hiding for critical fields. For example: 
     
    3636       , lastName    :: String 
    3737       , ...    
    38        }       sharing (customer_id, ...)  deriving (...)               -- new sharing syntax 
     38       }       sharing (Customer_id, ...)  deriving (...)               -- new sharing syntax 
    3939}}} 
    4040 
    41 TPDORF makes a virtue of this punning. (So extend's H98's and NamedFieldPuns punning on the field name.) This allows for some syntactic shortcuts, but still supporting H98-style declaring field names within the record decl for backwards compatibility. 
     41TPDORF makes a virtue of this punning. (So extend's H98's and `NamedFieldPuns` punning on the field name.) This allows for some syntactic shortcuts, but still supporting H98-style declaring field names within the record decl for backwards compatibility. 
    4242 
    4343Here is the `Has` class with instances for the above Customer record, and examples of use: 
     
    6666 
    6767   customer_id r = get r :: Customer_id                                 -- we can auto-decl this, see below 
     68   customer_id :: r{ customer_id :: Customer_id } => r -> Customer_id   -- type inferred for the function 
    6869 
    6970    myCust :: Customer                                                  -- usual record decl 
    70     ... myCust{ customer_id = 27 }                                      -- polymorphic record update 
     71    ... myCust{ customer_id = 27, firstName = Fred }                    -- **polymorphic** record update, no data constr 
    7172    ... (customer_id myCust) ...                                        -- field selection is func apply, or: 
    7273    ... myCust.customer_id ...                                          -- dot notation is sugar for reverse func apply 
     
    7576Note that the''' `Has` mechanism''' uses '''the field's type itself''' to locate the field within the record: 
    7677 * Each field must be a distinct type. 
    77  * The Type must be declared once (within the scope), and is then under regular name control.[[BR]](Probably you're doing this already for critical fields.) 
    78  * The field selector function also must be declared once, defined punning on the field's type. 
     78 * The Type must be declared once (within the scope), and is then under regular name control.[[BR]](Probably you're doing this already for critical fields to share.) 
     79 * The field selector function also must be declared once, defined punning on the field's type.[[BR]](See below for syntactic sugar to declare these.) 
    7980 
    8081    It is an error to be `sharing` a record field without there being a same-named type in scope. The desugar for the data decl would create the instance to use the Type, but then the instance would fail. 
    8182 
    82 To generate the correct declarations, there is to be a new `fieldLabel` sugar: 
     83To generate the correct field selector function, there is to be a new deriving class: 
    8384{{{ 
    84     fieldLabel customer_id :: r -> Int                                  -- new declaration, desugars to Proxy and func: 
    85     data Proxy_customer_id                                              -- phantom 
    86     customer_id :: r{ customer_id :: Int } => r -> Int                  -- r{ ... } is sugar for Has constraint 
    87     customer_id r = get r (undefined :: Proxy_customer_id) 
     85    newtype Customer_id = Customer_id Int                               -- newtype or data decl, same name type and constr 
     86                                           deriving (Has, ...)          -- generates customer_id function, per above 
    8887 
    89     set (undefined :: Proxy_customer_id) 27 myCust                      -- record update desugarred from above example 
     88    set (Customer_id 27) (                                              -- record update desugarred from above example 
     89               set (FirstName "Fred") myCust  )                         -- note nested 
     90 
     91    ... myCust{ cust_id, FirstName "Fred" }                             -- equiv syntax (assuming cust_id :: Customer_id) 
    9092}}} 
    9193 
    92  * (Admittedly, this could get onerous to declare a `fieldLabel` for every field, even the ones that appear in a single record type. See "Option Three: Mixed In-situ and DeclaredORF: " further down this page for a suggestion of using the DORF mechanism to generate one-off H98-style fields.) 
    9394 
    94 '''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): 
     95'''Virtual''' or '''pseudo-''' fields are easy to create and use, because field selection is merely function application (plus unwrapping for non-shared H98-style fields). Virtual fields look like ordinary fields (but can't be updated, because there is no `Has` instance): 
    9596{{{ 
    9697    fullName r = r.firstName ++ " " ++ map toUpper r.lastName           -- example adapted from SPJ 
     
    103104'''Technical capabilities''' and limitations for the `Has` class: 
    104105 * Monomorphic fields can be `get` and `set`. 
    105  * Parametric polymorphic fields can be applied in polymorphic contexts, and can be `set` including changing the type of the record. 
    106  * Higher-ranked polymorphic fields can be applied in polymorphic contexts, but cannot be set -- for the same reasons as under SORF.[[BR]]The instances use equality constraints to 'improve' types up to polymorphic. 
    107  * `Has` uses type family functions to manage type-changing update, which adds complexity -- see Implementer's view. 
     106 * Parametric polymorphic fields can be applied in polymorphic contexts, and can be `set` including changing the type of the record.[[BR]](This uses the SetResult type function.) 
    108107 * Multiple fields can be updated in a single expression (using familiar H98 syntax), but this desugars to nested updates, which is inefficient. 
    109108 * Pattern matching and record creation using the data constructor prefixed to { ... } work as per H98 (using `DisambiguateRecordFields` and friends). 
     109 * Higher-ranked polymorphic fields (including class-constrained) can be applied in polymorphic contexts, and can be set -- __providing__ they are wrapped in a newtype. 
    110110 
    111111.