Money and a rate from a snapshot
Intention
Section titled “Intention”I want to convert a foreign-currency amount at a rate for an explicitly supplied date.
An external indicator requires a snapshot — see Read an external limit from a snapshot. This scene applies the same contract to a Money rate on a date.
Incorrect form and why it stays silent
Section titled “Incorrect form and why it stays silent”external snapshot function Rate(on: Date) -> Money { capability "recipe.fx/1"; }A function without snapshot_from does not pin a rate source. Money / Money of one currency yields a share, multiplied by the price of one USD in KZT; adding currencies directly is forbidden.
Correct form
Section titled “Correct form”language "law.core" version "0.2";package recipes.l.r04 version "0.1.0";namespace "urn:recipe:l-calc:04";
external snapshot function Rate(on: Date) -> Money { capability "recipe.fx/1"; snapshot_from context.fx;}relation dollars(p: Text, amount: Money, on: Date);relation tenge(p: Text, amount: Money);rule Exchange strict { for p: Text; for amount: Money; for on: Date; when dollars(p, amount, on); then tenge(p, (amount / 1 USD) * Rate(on));}Frozen execution scene
Section titled “Frozen execution scene”| Facts and choice | Question | Answer |
|---|---|---|
| 1. 10 USD at 490 KZT | truth(tenge("invoice", 4900 KZT)) | TRUE_ONLY / COMPUTED |
| 2. 10 USD at the next day’s rate 495 KZT | truth(tenge("invoice", 4950 KZT)) | TRUE_ONLY / COMPUTED |
| 3. snapshot not presented | truth(tenge("invoice", 4950 KZT)) | NEITHER / EXTERNAL_UNAVAILABLE |
ten dollars at the dated rate
test "ten dollars at the dated rate" { 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 dollars("invoice", 10 USD, @2026-09-12); } evaluate truth(tenge("invoice", 4900 KZT)); expect truth_status == TRUE_ONLY; expect evaluation_status == COMPUTED;
}ten dollars at next day rate
test "ten dollars at next day rate" { 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 dollars("invoice", 10 USD, @2026-09-13); } evaluate truth(tenge("invoice", 4950 KZT)); expect truth_status == TRUE_ONLY; expect evaluation_status == COMPUTED;
}snapshot not presented
test "snapshot not presented" { 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 dollars("invoice", 10 USD, @2026-09-13); } evaluate truth(tenge("invoice", 4950 KZT)); expect truth_status == NEITHER; expect evaluation_status == EXTERNAL_UNAVAILABLE; expect issue(EXTERNAL_SNAPSHOT_MISSING);}The teaching snapshot is pinned by a semantic hash; resource bytes:
{ "schemaVersion": "law.core.external-snapshot/0.1", "id": "urn:recipe:l-calc:04:fx", "capability": "recipe.fx/1", "snapshotBinding": "context.fx", "calls": [ { "symbol": "urn:recipe:l-calc:04#Rate", "args": [ { "kind": "value", "type": { "name": "urn:law:std#Date" }, "value": "2026-09-12" } ], "result": { "kind": "value", "type": { "name": "urn:law:std#Money" }, "value": "490", "currency": "KZT" } }, { "symbol": "urn:recipe:l-calc:04#Rate", "args": [ { "kind": "value", "type": { "name": "urn:law:std#Date" }, "value": "2026-09-13" } ], "result": { "kind": "value", "type": { "name": "urn:law:std#Money" }, "value": "495", "currency": "KZT" } } ], "contentHash": "sha256:61f90adf1bb21fea0eec3bd638ed536cac7b31db8916e13f890b97b728137704"}Counterfactual
Section titled “Counterfactual”Mutation: snapshot_from context.fx; → “; expected LDC-E1305. Additional counterfactuals are shown as separate table rows.
Boundary
Section titled “Boundary”The snapshot is instructional, not an NBK rate. The input currency tag, the date and the rate source belong to the rule. A missing rate is not a zero price; HTTP is not called at evaluation time. The snapshot envelope carries a schema version: without it the request is refused before evaluation.
Pitfall
Section titled “Pitfall”Without a presented snapshot there is no rate and no zero price: the question stays Not established, not refuted, with EXTERNAL_SNAPSHOT_MISSING.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.