An attempt to solve the following problem: define a record, allow it to be read from JSON, and in addition allow mere subsets of its fields to be read from JSON.
- Non-invasive solution. The original record should be a plain one, without wrapping the fields in functors or a type family or something like that.
- Solution should not require specifying multiple "base records" or specifying the type of a given field more than once.
- Allow extracting individual fields from the parsed record, instead of having to process all the fields at once.
- The user should not be obliged to handle the possibility of
Nothing
s that he knows won't be there. - No TH
- Avoiding unsafeCoerce. Judicious uses of unsafeCoerce discreetly hidden in module internals should be ok.
- Optimizing compilation time.
The fields of the Subrec
are stored in a plain term-level map and their
different types are existencialized away. The constructor of the Subrec
is
hidden, so this is an internal detail. Only fields present in the type-level
list have entries in the map.
When accessing a field of the Subrec
, we require a HasField
instance
(provided by generic-lens) on the original record to ensure that the required
field exists on the record, and also to know what its type should be (thanks to
the functional dependency). We also check that the field name is present in the
list of selected fields. These conditions allow us to call unsafeCoerce
internally to get the field's value without fear of blowing up.
Check out the Subrec.Examples
module.
- How to deal with the "records problem" when writing REST API clients?
- Rich Hickey - Maybe Not The
- part at 23:55 about separating schema from selection.
- exinst could be useful
- surgery for data types. reddit.
- justified-containers
- ghosts of departed proofs
- fastsum Membership queries are constant-time, compiling to a single type-level natural lookup in a closed type family,
- type-map Maps where keys are types and values can have types depending on their keys.
- type-level-sets
- type-level-bst
- Parsing type-level strings in Haskell
- generics-sop, interaction with OverloadedRecordFields. Generic HasField.