Tagging constructors with record/product phantom type
|Reported by:||basvandijk||Owned by:|
|Type of failure:||None/Unknown||Test Case:|
|Related Tickets:||Differential Revisions:|
- Add a phantom type to the C type which specifies whether it's a record or a normal product using the empty datatypes:
data Record data Product
- Optionally add the type synonyms:
type R1 = M1 (C Record) type P1 = M1 (C Product)
- Optionally remove the conIsRecord method of the Constructor type class.
Of course GHC has to be modified too, so that the generated Cs are properly tagged.
Having the information, whether a constructor is a record or not, statically available instead of only dynamically, has the following advantages:
- More efficient: programs can make a static instead of a dynamic choice. (To be fair, the case branches on conIsRecord should in most cases be optimized away)
- No unnecessary constraints for constructor instances:
See the code that triggered this proposal:
instance (Constructor c, GRecordToObject a, GToJSON a) => GToJSON (C1 c a) where gToJSON m1@(M1 x) | conIsRecord m1 = Object $ gRecordToObject x | otherwise = gToJSON x
Note the GRecordToObject constraint. This constraint is only really necessary in case of a record. Down the line this extra constraint requires the following ugly undefined instances:
instance GRecordToObject (a :+: b) where gRecordToObject = undefined instance GRecordToObject U1 where gRecordToObject = undefined instance GRecordToObject (K1 i c) where gRecordToObject = undefined instance GRecordToObject (M1 i c f) where gRecordToObject = undefined
Since GHC.Generics is part of the ghc-prim package I don't think this proposal has to go through the whole library submission process. But if it must I will have no problem supervising it.