Exercise 10. The same date via two norms
An exercise for the from article text to
norm page. On the page the benefit grant
date is computed by one term: max(from, registered). The same meaning
can be written as two norms with guards, a record closer to the article
text, where two cases are named apart.
Setup. Replace the one max norm with two norms: if disability was
established no earlier than the application registration, benefit is
granted from the establishment date; if earlier, from the registration
date. On all three cases the answer must match the max form:
| Established | Application registered | Grant date |
|---|---|---|
| 15 January 2026 | 10 March 2026 | 10 March 2026 |
| 10 March 2026 | 15 January 2026 | 10 March 2026 |
| 10 March 2026 | 10 March 2026 | 10 March 2026 |
Hint. The third row is the boundary. One of the two norms must take equality, and only one: two norms with one head and one value would give the same answer, but sloppily.
Below is the solution. Try it yourself first.
Solution
Section titled “Solution”language "law.core" version "0.2";package tutorial.kz.social version "0.2.1";namespace "urn:law:tutorial:kz:social";
entity Actor;entity Person : Actor;entity DisabilityStatus;entity Benefit;entity BenefitApplication;
const DisabilityBenefit: Benefit = entity_ref("urn:law:tutorial:kz:social#DisabilityBenefit") { label ru-KZ official "Пособие по инвалидности";};
relation disability_established(person: Person, status: DisabilityStatus, from: Date) kind institutional;relation entitled(person: Person, benefit: Benefit) kind institutional;relation application_for(application: BenefitApplication, person: Person, benefit: Benefit) kind empirical;relation application_registered(application: BenefitApplication, day: Date) kind institutional;relation benefit_start_date(person: Person, benefit: Benefit, day: Date) kind institutional;The label reads: “Disability benefit”.
Two norms. Equality goes to the first:
@source("KZ-SOCIAL-CODE-224-VII-ART-175")rule DisabilityBenefitStartFromDisability strict { label ru-KZ official "Статья 175. Назначение с даты установления инвалидности"; for person: Person; for status: DisabilityStatus; for from: Date; for application: BenefitApplication; for registered: Date; when entitled(person, DisabilityBenefit) and disability_established(person, status, from) and application_for(application, person, DisabilityBenefit) and application_registered(application, registered) and from >= registered; then benefit_start_date(person, DisabilityBenefit, from);}
@source("KZ-SOCIAL-CODE-224-VII-ART-175")rule DisabilityBenefitStartFromApplication strict { label ru-KZ official "Статья 175. Назначение с даты регистрации заявления"; for person: Person; for status: DisabilityStatus; for from: Date; for application: BenefitApplication; for registered: Date; when entitled(person, DisabilityBenefit) and disability_established(person, status, from) and application_for(application, person, DisabilityBenefit) and application_registered(application, registered) and from < registered; then benefit_start_date(person, DisabilityBenefit, registered);}The labels read: “Article 175. Grant from the disability establishment date” and “Article 175. Grant from the application registration date”.
Which form is better. max is shorter and has no boundary to lose. Two
norms read as the article’s two cases and each gets its label: in
verbalisation and in the derivation explanation, the answer’s consumer
will see which case fired. Both forms are correct; the choice is
about what matters more to show the answer’s reader.
The setup’s three rows execute on this package. The fourth
check is a counterfactual: without the and from >= registered guard,
the first norm grants benefit from the establishment date on the first
case too. The answer to the 10 March question stays TRUE_ONLY, but the
15 January question also answers TRUE_ONLY: one person holds two grant
dates at once. A key over person and benefit does not catch this: it
reconciles case facts, not norm conclusions, and declares no conflict.
This page’s first version promised BOTH here, and the check corrected
it.
What the exercise teaches. Two norms’ guards must cover the axis without
gaps or overlaps: >= and <. A gap yields NEITHER on the boundary,
an overlap two values the engine silently holds side by side. The
compiler sees neither mistake; only a boundary case and a wrong-date
question catch them.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.