Distinguish an enum member from a data variant
Intent
Section titled “Intent”I want to keep enum identity and a variant’s payload.
Wrong form and why it stays silent
Section titled “Wrong form and why it stays silent”enum Kind { Local = "Local"; Foreign; }An enum member is its own qualified identity, not a string. A variant with fields is a different data device; cross-package qualification of members is checked by a separate witness below.
Correct form
Section titled “Correct form”language "law.core" version "0.2";package recipes.g.r10 version "0.1.0";namespace "urn:recipe:g-concepts:10";
entity Person;enum Kind { Local; Foreign; }type Identifier = NationalId { value: Text; } | ForeignId { scheme: Text; value: Text; };relation category(p: Person, k: Kind);relation identification(p: Person, id: Identifier);relation eligible(p: Person);rule LocalOnly strict { for p: Person; when category(p, Local); then eligible(p); }Frozen execution scene
Section titled “Frozen execution scene”| Facts on 13.09.2026 | Question | Answer |
|---|---|---|
| local category | truth(eligible(entity_ref("urn:recipe:g-concepts:10:p"))) | truth_status == TRUE_ONLY; / COMPUTED |
| other category | truth(eligible(entity_ref("urn:recipe:g-concepts:10:p"))) | truth_status == NEITHER; / COMPUTED |
| variant with payload | truth(identification(entity_ref("urn:recipe:g-concepts:10:p"), NationalId { value: "123" })) | truth_status == TRUE_ONLY; / COMPUTED |
local category qualifies
test "local category qualifies" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert category(entity_ref("urn:recipe:g-concepts:10:p"), Local); } evaluate truth(eligible(entity_ref("urn:recipe:g-concepts:10:p"))); expect truth_status == TRUE_ONLY; expect evaluation_status == COMPUTED;}foreign category stays unknown
test "foreign category stays unknown" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert category(entity_ref("urn:recipe:g-concepts:10:p"), Foreign); } evaluate truth(eligible(entity_ref("urn:recipe:g-concepts:10:p"))); expect truth_status == NEITHER; expect evaluation_status == COMPUTED;}loaded variant identifies
test "loaded variant identifies" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert identification(entity_ref("urn:recipe:g-concepts:10:p"), NationalId { value: "123" }); } evaluate truth(identification(entity_ref("urn:recipe:g-concepts:10:p"), NationalId { value: "123" })); expect truth_status == TRUE_ONLY; expect evaluation_status == COMPUTED;}Two synthetic packages: the dependency is pinned by a generated law.lock. In the correct consumer the type and the member are qualified. For the second test only kind == recipes.g.owner10::first is replaced with kind == first: lowering succeeds without an error, but this is a LocalKind member, and the comparison yields TYPE_ERROR.
language "law.core" version "0.2";package recipes.g.owner10 version "0.1.0";namespace "urn:recipe:g-concepts:10:owner";pub enum ForeignKind { first; second; }language "law.core" version "0.2";package recipes.g.consumer10 version "0.1.0";namespace "urn:recipe:g-concepts:10:consumer";import recipes.g.owner10 version "0.1.0";entity Person;enum LocalKind { first; other; }relation chosen(p: Person, kind: recipes.g.owner10::ForeignKind);relation eligible(p: Person);rule Choose strict { for p: Person; for kind: recipes.g.owner10::ForeignKind; when chosen(p, kind) and kind == recipes.g.owner10::first; then eligible(p);}imported member qualifies
language "law.core" version "0.2";package recipes.g.consumer10 version "0.1.0";namespace "urn:recipe:g-concepts:10:consumer";
test "imported member qualifies" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert chosen(entity_ref("urn:recipe:g-concepts:10:p"), recipes.g.owner10::first); } evaluate truth(eligible(entity_ref("urn:recipe:g-concepts:10:p"))); expect truth_status == TRUE_ONLY; expect evaluation_status == COMPUTED;}bare member fails comparison
language "law.core" version "0.2";package recipes.g.consumer10 version "0.1.0";namespace "urn:recipe:g-concepts:10:consumer";
test "bare member fails comparison" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert chosen(entity_ref("urn:recipe:g-concepts:10:p"), recipes.g.owner10::first); } evaluate truth(eligible(entity_ref("urn:recipe:g-concepts:10:p"))); expect truth_status == NEITHER; expect issue(TYPE_ERROR); expect evaluation_status == TYPE_ERROR;}>>> import runpy>>> check = runpy.run_path("docs/recipes/g-concepts/resources/check.py")>>> check["check_import"]()'Г10: квалифицированный член TRUE_ONLY; голый член TYPE_ERROR; lawc = lawref'Counterfactual
Section titled “Counterfactual”Mutation enum Kind { Local; Foreign; } → enum Kind { Local = "Local"; Foreign; }: LDC-E0206.
Boundary
Section titled “Boundary”A bare member name is resolved in the current package. In an importing package pkg::Member is required; qualifying the type does not qualify each value for the author.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.