Open jackfirth opened 5 years ago
Notes on API designs currently being explored:
The guard functions should accept values for each field and an extra value with information about the type, so the guard function can raise errors that use the type's name and field names.
The type information should usually be given first, then the guard should return a function that accepts the field values. This allows a guard to make assertions about the shape of the type. Tuple guards (#203) and record guards (#204) both need this feature, but wrapper guards (#202) don't.
Currently, guards are just plain functions. But maybe they should be functions wrapped by a struct, to make it easier to check first-order properties about them and to make the guard APIs easier to work with.
Guards are most important for types that are usually used as plain bags of data (wrappers, tuples, records), rather than types that seal away some opaque fields (reference types). The former are much higher priority than the latter.
Singleton type guards seem pointless.
Guards ought to be able to normalize and convert field values. This makes them slightly more powerful than plain chaperone contracts, since they don't have to return equal?
values. But they're not applied on field accesses, only on instance construction. Additionally, this normalization should be idempotent.
Guards ought to be able to check constraints across multiple fields. Example: a bounds
tuple type with a min
field and a max
field should enforce that min <= max
. This might require a dependent contract combinator, or maybe there's room for some sort of "multicontract" API.
Combined with #177, this would allow deleting a ton of the boilerplate associated with defining and providing a non-generic data type. Candidates within rebellion include:
rebellion/media
rebellion/media/application/octet-stream
rebellion/point
rebellion/media/text/plain
rebellion/web-graph
rebellion/web-link
The API for this seems mostly designed for now, see the three subtasks.
Analogous to
struct-guard/c
, there should bexxx-guard/c
contract combinators for use with each kind of type inrebellion/type
. They should provide APIs similar to the constructors of the kind of types they're meant for. Subtasks: