高階関数の境界条件は「関数値がgraph形状決定位置に到達しない」ことである
graph出力DSLに高階関数を入れる核心は属性値計算の自由度を上げることにあるが、その自由度がgraph形状側(resource生成位置 / module選択位置 / identity決定位置)に染み出すと、「実装の切替」自由度を言語側で縛る不変条件が壊れる。したがって境界設計の必要条件は、関数値がresource生成位置・module選択位置・identity決定位置に到達しないという型/文法境界である。
禁じる必要があるパターンは次の形で書ける。
fn pick_module(env: string) -> Module { ... }
let net = (pick_module("prod")) { cidr = "..." } # 関数呼び出し結果をmodule callの起点に
これを許すと、Carinaの現行の不変条件(sourceはリテラル文字列限定、use式はlet束縛RHSのみ)が骨抜きになる。
重要なのは、「実装の切替」のgraph形状側だけを厳格分離するだけでは十分条件にならないという点である。属性値レベルの関数値が、参照やbooleanを介して後段のfor / if / module選択に流れれば、結局graph形状を変えうる。つまり禁止すべきなのは「関数がModuleを返すこと」という一点ではなく、関数値が形状決定位置に到達する経路すべてである。
制約の置き場所として三つの選択肢がある。
- 型レベル制約:
Module型を関数の戻り値型/引数型に置けないようにする。さらにresource typeも関数値で扱えないようにする - 文法レベル制約: module call (
name { ... })の起点に式を許さず識別子のみ許す。resource declarationの起点も同様に識別子のみ - 評価レベル制約:関数値がmodule call / resource生成位置に評価された場合はparse/evaluatorで弾く
AI時代の文脈ではこの境界の緩さは、plan予測精度とAI検証性の悪化として現れる。境界設計が緩いとplanがunknownだらけになり、人にもAIにも判別不能になる。またtags = compose(f, g, h)(env)のような複雑な合成は、graph形状を変えずとも属性監査を破綻させうる。
根拠の確度
境界設計の技術的成立性は未検証。上記の型/文法/評価制約が実装可能かどうかは、carina#2238で議論中の未決の論点である。