docs← Back to article

Markdown for LLMs

Exercise 7. A bulk-order discount

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# Exercise 7. A bulk-order discount

An exercise for the [numbers and money](/tutorials/numbers/) page. The
page's package computes copy fees and knows the bulk-order threshold:
over a hundred pages.

**Setup.** Introduce a ten-percent discount for bulk orders. An order of
101 pages must receive the discounted fee `13635.00 KZT`; an order of
seven pages gets no discount at all: the discounted-fee question answers
`NEITHER`, not "zero discount".

**Hint.** A rate is not a number but a share: see how the researcher rate
is declared on the page. Rounding must be explicit.

Below is the solution. Try it yourself first.

## Solution

The header, relations, and constants from the page, plus one relation
and one constant:

```law
language "law.core" version "0.2";
package tutorial.archive version "0.13.1";
namespace "urn:law:tutorial:archive";

entity Person;
entity CopyOrder;

relation copy_order(o: CopyOrder, p: Person, pages: Integer) kind empirical { key(o); }
relation copy_fee(o: CopyOrder, amount: Money) kind institutional { key(o); }
relation bulk_fee(o: CopyOrder, amount: Money) kind institutional { key(o); }

const PAGE_RATE: Money = 150 KZT;
const BULK_PAGES: Integer = 100;
const BULK_RATE: Decimal = 90 percent;

rule CopyFee strict {
    for o: CopyOrder;
    for p: Person;
    for n: Integer;
    when copy_order(o, p, n);
    then copy_fee(o, n * PAGE_RATE);
}
```

The discount norm reads the already computed fee rather than computing
it again:

```law
rule BulkDiscount strict {
    for o: CopyOrder;
    for p: Person;
    for n: Integer;
    for a: Money;
    when copy_order(o, p, n) and n > BULK_PAGES and copy_fee(o, a);
    then bulk_fee(o, round(a * BULK_RATE, 2, "HALF_UP"));
}
```

Why `NEITHER` on seven pages is more correct than a zero discount. The
archive rules do not say "the small-order discount is zero"; they are
silent about small orders. A norm deriving zero would be a statement the
text lacks, and a consumer asking "what is the discount" would receive an
answer instead of the honest "there is no discount".

## Check

| Facts | Question | Answer |
|---|---|---|
| order of 101 pages | `bulk_fee(order1, 13635.00 KZT)` | `TRUE_ONLY` |
| order of 101 pages | `bulk_fee(order1, 13635 KZT)` | `TRUE_ONLY` |
| order of 7 pages | `bulk_fee(order1, 945.00 KZT)` | `NEITHER` |
| 101 pages, without the `BulkDiscount` norm | `bulk_fee(order1, 13635.00 KZT)` | `NEITHER` |

The second row checks one misconception: a rounded sum prints with two
decimal places, but money compares as magnitudes, and `13635 KZT` is the
same sum. This page's first version promised `NEITHER` here, and the check
corrected it.

What the exercise teaches. A derived-magnitude norm rests on another
norm's head rather than repeating its computation: if the page rate
changes, the discount recomputes itself. The rate is declared a share,
rounding explicit, both decisions visible in the package text.