Records/DeclaredOverloadedRecordFields/ImplementorsView: DORF Prototype Importing 29Feb2012.lhs

File DORF Prototype Importing 29Feb2012.lhs, 4.9 KB (added by AntC, 15 months ago)

demo importing and namespace control of field clashes

Line 
1> {-# OPTIONS_GHC -XDisambiguateRecordFields -XNamedFieldPuns -XRecordWildCards #-}
2> {-# OPTIONS_GHC -XTypeFamilies        -XFlexibleContexts                      #-}
3> {-# OPTIONS_GHC -XRankNTypes  -XImpredicativeTypes -XGADTs -XEmptyDataDecls   #-}
4> {-# OPTIONS_GHC -XMultiParamTypeClasses -XFlexibleInstances -XUndecidableInstances   #-}
5
6> module DORFCRM        where
7>
8import DORF    hiding (lastName, firstName, Proxy_lastName, Proxy_firstName)
9>                                                         -- Note: import is _not_ qualified
10
11
12------------------ fieldLabel decls (for 'monomorphic' fields) -------------------------------------
13
14   -- fieldLabel customer_id :: r -> Int                  -- already decl'd in Module DORF
15                                                          -- so we're going to share it
16
17
18   fieldLabel firstName :: r -> String                    -- same Label as in the imported module, but we've hidden the import
19
20data Proxy_firstName
21-- firstName :: (Has r Proxy_firstName t, t ~ String) => r -> String
22firstName r = get r (undefined :: Proxy_firstName)
23>
24type instance GetResult r Proxy_firstName t = String    -- firstName always a String, for all record types
25>
26
27   fieldLabel lastName :: r -> String                     -- also same label as in imported DORF
28
29data Proxy_lastName
30-- lastName :: (Has r Proxy_lastName t, t ~ String) => r -> String
31lastName r = get r (undefined :: Proxy_lastName)
32>
33type instance GetResult r Proxy_lastName t = String    -- firstName always a String, for all record types
34
35
36------------------Virtual field definition (note no Has instance needed, so no need to worry about set) ----
37
38-- fullName r = firstName r ++ " " ++ lastName r           -- is imported from DORF
39>                                                             -- but defined only for DORF.firstName, DORF.lastName
40
41
42
43------------------Record decl, and Has instance generated (for 'monomorphic' fields)----------------------------
44
45data Customer_Contact = Cust_Cont { customer_id____ :: Int, firstName__, lastName__ :: String }
46>                              deriving (Eq, Show, Read)
47>                                                    -- suffixing the field name to avoid clash
48>
49type instance SetResult Customer_Contact fld t = Customer_Contact
50>                                        -- Customer_Contact has no type params
51>
52>                                        -- note: GetResult type instances already decl'd, by field
53>
54instance (t ~ Int) => Has Customer_Contact Proxy_customer_id t         where   -- using imported customer_id
55>      get Cust_Cont{customer_id____} _ = customer_id____
56>      set _ x Cust_Cont{..}  = Cust_Cont{customer_id____ = x, .. }
57>
58instance (t ~ String) => Has Customer_Contact Proxy_firstName t        where   -- using local firstName
59>      get Cust_Cont{firstName__} _ = firstName__
60>      set _ x Cust_Cont{..}  = Cust_Cont{firstName__ = x, .. }
61>
62instance (t ~ String) => Has Customer_Contact Proxy_lastName t         where   -- using local lastName
63>      get Cust_Cont{lastName__} _ = lastName__
64>      set _ x Cust_Cont{..}  = Cust_Cont{lastName__ = x, .. }
65>
66
67----------------- tests ---------------------------------------------------------------------------------------
68
69rCC1 =   Cust_Cont{ customer_id____ = 57, firstName__ = "Fred", lastName__ = "Daggy" }
70>
71-- customer_id rCC1    ==> 57                                -- sharing customer_id
72-- firstName rCC1 ++ " " ++ lastName tCC1      ==> "Fred Daggy"
73>
74-- lastName rCN0       ==>  No instance for (Has Customer_NameAddress Proxy_lastName t0)
75--                               arising from a use of `lastName'
76-- DORF.lastName rCC1  ==> No instance for (Has Customer_Contact DORF.Proxy_lastName t0)
77--                              arising from a use of `DORF.lastName'
78>
79-- fullName    rCC1    ==> No instances for (Has Customer_Contact DORF.Proxy_firstName t0,
80--                                            Has Customer_Contact DORF.Proxy_lastName t10)
81--                              arising from a use of `fullName'
82>
83
84     To explain that failure on fullName:
85          We imported fullName, defined against the fieldLabel proxys in Module DORF.
86          And we imported customer_id defined similarly,
87                 instanced Customer_contact against the shared Proxy_customer_id
88          But we defined local versions of the name fieldLabels,
89                 so fullName wasn't instanced against them.
90
91     This shows that within a single record decl:
92          1. You can create fields that share Labels with imports.
93          2. You can create fields that don't share, even with the same Label name.
94                 (That is, the module system continues to control the namespace.)
95          3. You can prevent using the wrong field selector with the wrong record type,
96                 even if they have the same Label name.
97