gen.attrsOf: attrsets with generated keys #4

Closed
opened 2026-09-13 20:04:00 +09:00 by natsukium · 2 comments
Owner

Missing

gen.attrsOf lenRange keyGen valueGen (a map with generated keys), the attrset counterpart of gen.listOf.

Where it was needed

jsonschema2nix generates values for JSON Schema maps (additionalProperties). Only the number of keys can vary today; the keys come from a fixed list:

freeformNames = [ "extraOne" "extraTwo" ];
gen.record (lib.genAttrs (lib.take n freeformNames) (_: valueGen))

So a property over maps never sees a key that matches propertyNames / patternProperties patterns, a key that collides with a declared property name, or more than two entries, and shrinking cannot drop individual keys, only shorten the prefix.

Suggested shape

  • gen.attrsOf lenRange keyGen valueGen, deduplicating keys, shrinking by removing entries (like listOf) and by shrinking each key and value.
  • gen.attrsWith keys valueGen for a subset of a known key list, shrinking toward fewer keys.
## Missing `gen.attrsOf lenRange keyGen valueGen` (a map with generated keys), the attrset counterpart of `gen.listOf`. ## Where it was needed jsonschema2nix generates values for JSON Schema maps (`additionalProperties`). Only the number of keys can vary today; the keys come from a fixed list: ```nix freeformNames = [ "extraOne" "extraTwo" ]; gen.record (lib.genAttrs (lib.take n freeformNames) (_: valueGen)) ``` So a property over maps never sees a key that matches `propertyNames` / `patternProperties` patterns, a key that collides with a declared property name, or more than two entries, and shrinking cannot drop individual keys, only shorten the prefix. ## Suggested shape - `gen.attrsOf lenRange keyGen valueGen`, deduplicating keys, shrinking by removing entries (like `listOf`) and by shrinking each key and value. - `gen.attrsWith keys valueGen` for a subset of a known key list, shrinking toward fewer keys.
Author
Owner

Plan

Hedgehog Gen.map retries on duplicate keys; Hypothesis dictionaries and fast-check dictionary drop them. nixcheck has no discard machinery yet, so start with drop-duplicates:

attrsOf = lenRange: k: v: map builtins.listToAttrs (listOf lenRange (record { name = k; value = v; }));

listToAttrs keeps the first occurrence (verified), so the result is deterministic; the entry count can be below the drawn length, same as Hypothesis. Document it. Switch to retrying once #9 (gen.filter / discards) exists.

attrsWith keys valueGen = bind (subsequence keys) (ks: record (genAttrs ks valueGen)), with gen.subsequence from #11 (each key kept by a bool that shrinks true -> false, so the attrset shrinks toward { }).

Shrinking individual keys is limited by listOf only dropping a suffix; #13 (chunk-removal list shrinking) fixes that for lists and attrsets at once.

## Plan Hedgehog `Gen.map` retries on duplicate keys; Hypothesis `dictionaries` and fast-check `dictionary` drop them. nixcheck has no discard machinery yet, so start with drop-duplicates: ```nix attrsOf = lenRange: k: v: map builtins.listToAttrs (listOf lenRange (record { name = k; value = v; })); ``` `listToAttrs` keeps the first occurrence (verified), so the result is deterministic; the entry count can be below the drawn length, same as Hypothesis. Document it. Switch to retrying once #9 (`gen.filter` / discards) exists. `attrsWith keys valueGen` = `bind (subsequence keys) (ks: record (genAttrs ks valueGen))`, with `gen.subsequence` from #11 (each key kept by a `bool` that shrinks `true -> false`, so the attrset shrinks toward `{ }`). Shrinking individual keys is limited by `listOf` only dropping a suffix; #13 (chunk-removal list shrinking) fixes that for lists and attrsets at once.
Author
Owner

Implemented in e7270a3, pushed to main.

Implemented in e7270a3, pushed to main.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
natsukium/nixcheck#4
No description provided.