日本語 · English(未訳)

表現力検証 4: 射影一族の綻び出し

ADR-27 で導入した窓→値の射影一族ordinalIn/labelOf/epochOrdinal/snapTo+窓ラベル付与 label:)は、01〜03 の「要補完」判定をまとめて救うはずの機構だが、名も含めて綻び出し前の候補段階 だった。本書はその候補を 01〜03 の該当例に実際に適用して書き直し、機構の穴を炙り出す。綻びは 90-findings.md(F34〜)へ。方法論は他章と同じ「書いて綻びを見る」。

4.0 現行案(ADR-27・spec §4.9)の要約

語(仮称) 意味
ordinalIn(w, d) 点 → 数値 d が属する w 窓の中で第何要素か(1 起点・窓ごとリセット)
epochOrdinal(w, d) 点 → 数値 属する w 窓の紀元からの通し序数
labelOf(w, d) 点 → ラベル/値 d の属する w 窓のラベル(cycle ラベル読みの一般形)
snapTo(w) ストリーム変換 各点を属する w 窓の先頭点へ写す(floor)
label:(付与) 窓生成の引数 窓インスタンスにラベル式を貼る(未確定)

以下、各サンプルを射影で書き、綻びに F 番号を振る。


4.1 暦座標(yearNo・monthNo・dayNo)は射影で導けるか

固定日祝日・イースター時点化・給料日などが要求する「点の暦座標」を、まず射影一族から導出してみる。 標準 premise(stdlib/gregorian.md)は既に月通し番号 m からの値関数 yearOf(m)monthOf(m) を持つ。 点から m を出せれば、暦座標はその合成になる。

# 点 → その点が属する月の通し番号(紀元起点)
m(d)       = epochOrdinal(month, d)
yearNo(d)  = yearOf(m(d))            # 2026(既存値関数の再利用)
monthNo(d) = monthOf(m(d)) + 1       # 1〜12
dayNo(d)   = ordinalIn(month, d)     # 月内日序数 1〜31

判定: 導ける。暦座標は射影一族の新規語ではなく糖衣epochOrdinalordinalIn+既存値関数)だと 確かめられた。固定日祝日(毎年 2/11)は filter(d => monthNo(d) == 2 and dayNo(d) == 11)、イースターは filter(d => monthNo(d) == easterMonth(yearNo(d)) and dayNo(d) == easterDay(yearNo(d))) で書ける。

綻び:

4.2 固定日祝日 — ordinalIn の「月内序数」と「日」の食い違い

@Gregorian
foundationDay = everyDay |> filter(d => monthNo(d) == 2 and dayNo(d) == 11)   # 建国記念の日

dayNo(d) = ordinalIn(month, d) は「その月の第何日」。2/11 なら 11。期待通り(01 §1.1 の onMonthDay 糖衣を射影で厳密化できた。cycle ラベル述語に頼らずに済む)。

判定: 書ける。01 の「要補完」が射影で解ける。

綻び:

4.3 六曜 — labelOf のラベルの「源」が定まらない

@Lunisolar
rokuyoIndex = d => (lunarMonthNo(d) + ordinalIn(lunarMonth, d)) mod 6
lunarMonthNo(d) = labelOf(lunarMonth, d)     # 旧暦の月番号(1〜12、閏月は前月番号)

ordinalIn(lunarMonth, d)(旧暦月窓内の日序数)は素直。問題は labelOf(lunarMonth, d)。旧暦の月番号は 中気を含むかで決まり(雨水を含む月=1 月)、閏月は番号を持たない(前月名を継ぐ)。この番号は窓の 自然な序数でも cycle の固定巡回でもない——計算して貼ったラベルである。つまり labelOf が読むには、 先に lunarMonth 窓へラベルを付与label:)しておく必要がある。

判定: 要補完label: 付与が未確定のまま)。読み(labelOf)だけ導入しても、貼る側が無ければ 読むものが無い。

綻び:

4.4 立春の選択(F33 の解決を射影で試す)

03 §3.3 で露見した「立春を序数で選べない」(F33)を射影で解こうとする。

# 案 A: 節気点に名前ラベルを付与(label:)して labelOf で読む
sekkiLabeled = sekkiInstants |> label: cycle [小寒, 大寒, 立春, 雨水, …24個…]   # 時点列に巡回ラベル
risshun      = sekkiLabeled |> filter(s => labelOf(sekki, s) == 立春)

# 案 B: 黄経で選ぶ(節気=黄経 15°刻み。立春=315°)
risshun      = sekkiInstants |> filter(s => solarLongitude(s) == 315)

判定: 案 A は書けるが、label:区間列型でない裸の点列sekkiInstants)に貼る形になり、cycle が 「点に巡回ラベル」を貼る本来(day 窓など単位窓へ)とずれる。案 B の solarLongitude(s) は連続天文量で 射影一族の外(データ)。

綻び:

4.5 ISO 週番号 — ordinalIn では規約が出ない

@ISO   # wkst: Mon
isoWeekNo(d) = ordinalIn(year, weekOf(d))   # 年内で週が第何番目?

ISO 8601 の週番号は「その年の第 1 木曜を含む週=W01」。単純な「年内の第何週」ではない(年初の数日が 前年の最終週 W52/W53 になる、年末が翌年 W01 になる)。素の ordinalIn(year, week) では出ない。

判定: 要補完ordinalIn は素の序数で、ISO の木曜規約を表現できない。

綻び:

4.6 snapTo と公開境界語の重複

snapTo(month)         # 各点 → その月の初日(floor)
month |> first        # 各月窓 → その先頭点(選択子)
Gregorian.monthStart  # 公開境界語(= month |> first)

snapTo(month) は「点→窓先頭点」、monthStart は「窓→先頭点」。入口(点かストリームか窓か)が違うが 同じ『月の初日』を三経路で出せる。節気の瞬間を日に丸める(03 F21)には snapTo(day) が要ったが、 これは「窓の先頭点」という窓属性の読み——labelOf の値がラベルでなく境界点の版とも言える。

判定: 書けるが機構が重複ぎみ。

綻び:

4.7 「n 個ごと窓リセット」ストライドの還元(ADR-27 の主張の検算)

ADR-27 は「ストライドの窓ごとリセット版は filter(d => (ordinalIn(w, d) - 1) mod n == 0) に還元され 専用記法を持たない」とした。検算する。

# 各月の 1・4・7・…日目(3 日ごと・月頭でリセット)
@Gregorian
everyDay |> filter(d => (ordinalIn(month, d) - 1) mod 3 == 0)

判定: 書ける。月頭で位相がリセットされ、ordinalIn が月内序数なので mod 3 が月ごとに 1 から数え 直す。ADR-27 の主張は成立。

綻び:


小括 — 射影一族に必要な設計判断

01〜03 の「要補完」は射影一族で大半が書けた(固定日祝日・イースター・六曜の骨格・窓リセット)。 だが綻び出しで、候補のままでは決められない設計判断が六つ見えた。

判断 綻び 方向の当たり  
ordinalIn/epochOrdinal の引数設計(数える対象と枠) F34 二窓引数 ordinalIn(数える窓, 枠窓, d) に一本化を検討  
射影値は入力ストリームの粒度に依存する F35・F42 「窓の下位窓を数える」版(粒度非依存)と「入力要素を数える」版の分離  
labelOf が読むラベルの源(cycle/label:/暦座標) F36 「窓はラベルを一つ持ち源は生成時に決まる」モデルの明文化  
窓ラベル付与 label: の表現力(隣接窓・別点の窓の参照) F37・F40 隣接窓は射程外(データに倒す)、別点の窓参照(ISO 週・年度)は要設計  
ラベル付きテーブルリテラル(時点+ラベル列) F38・F39 ADR-26 を「列を持つ表」へ拡張。cycle(律動)と表の列(1 対 1)を分ける  
snapTo と選択子・公開境界語の重複 F41 snapTo(w) を「点→属する w 窓 > first」の糖衣として new 語を減らす

総括: 射影一族は「暦座標は糖衣で導ける(新規語は epochOrdinalordinalIn の二つで足りる)」ことが 確認できた一方、labelOfラベルの源の三分類付与 label: の設計が本体で、そこが未決のまま だと六曜の月名・ISO 週番号・年度ラベル・節気名が書けない。次段は (a) ordinalIn/epochOrdinal の二窓 引数への一本化、(b) labelOf のラベル源モデル、(c) label: 付与+ラベル付きテーブルの設計——この三点を 詰める(draft §1.17 の改稿と ADR-27 の改訂)。snapTo は糖衣化で新規語から外せる見込み。