# View Contracts and View Trees ## 1. Purpose View Contracts are the portable checking layer for Tree Calculus programs. The checker does not consume detached metadata about a separate executable. Its canonical input is a typed, checkable tree artifact: ordinary tree data that contains both the executable program payloads and the view/contract structure needed to validate and transform them. The checker consumes this artifact and returns either: ```text checked-execution artifact ``` or: ```text structured diagnostic ``` A checked-execution artifact is interpreted by `runChecked`. Unguarded programs are represented as `checkedPure rootPayload`; guarded programs contain explicit checked guard/bind nodes. This keeps checking independent of any particular host implementation. A typed artifact may be produced by any frontend, compiler, hand-written generator, or future self-hosted `tricu` toolchain. ## 2. Design Principle The model follows the same discipline as interaction trees. Interaction trees use tagged structural envelopes with explicit executable payloads: ```tri io action = pair "tricuIO" (pair version action) pure x = pair 0 x bind action k = pair 1 (pair action k) ``` The interpreter understands the outer structure, but it does not recursively mistake every subtree for interpreter metadata. A continuation `k` is an opaque executable tree until the interpreter reaches the `bind` step that applies it. View trees use the same rule: ```text structure says how to check; opaque executable fields are only executed/applied by the checker at the appropriate step. ``` This is the key distinction that allows Views to carry guards without confusing ordinary program trees with View metadata. ## 3. Views A View is an extrinsic contract over an ordinary Tree Calculus value. Tree Calculus values do not carry native runtime types; a View describes how a value may be treated by the checker or by a checked boundary. Core View forms: ```text Any Ref ref Fn [argView...] resultView List elemView Maybe elemView Pair leftView rightView Result errView okView Guarded baseView guard ``` `Ref` supports both generated/numeric and symbolic references. Symbolic refs are preferred for user-authored views: ```tri UserId = viewRef "UserId" ``` A guarded view refines a base view with an executable guard: ```tri UserId = viewGuarded (viewRef "UserId") userIdGuard ``` The guard is ordinary program code. The View validator checks that the guarded view envelope is well-formed, and recursively validates the `baseView`, but it must treat the guard payload/reference as opaque executable data, not as another View. ## 4. Polymorphic and Abstract Views View Contracts support portable polymorphism over Views. The View language is interpreted by the same portable checker model implemented in `tricu` terms. Source syntax may use underscore-prefixed names as View variables inside annotations: ```tri id x@_a =@_a x const x@_a y@_b =@_a x compose f@(Fn [_b] _c) g@(Fn [_a] _b) x@_a =@_c f (g x) ``` In the portable artifact, these lower to scoped View binders rather than unscoped source-name conventions. This fits the existing View encoding style: Views are tagged records with numeric tags and tagged fields. Polymorphic forms are View records such as: ```text Var localId Forall binders body Exists binders body ``` The current durable encoding uses stable local binder IDs. For example, `id x@_a =@_a x` exports a shape equivalent to: ```text Forall [0] (Fn [Var 0] (Var 0)) ``` Source names like `_a` are for authoring; the artifact carries binder scope and local IDs rather than relying on source-name identity. `Forall` supports generic contracts: ```tri map f@(Fn [_a] _b) xs@(List _a) =@(List _b) ... head xs@(NonEmptyList _a) =@_a ... ``` At each checked use, the checker instantiates quantified variables into use-local internal variables and solves View compatibility constraints. The portable checker uses structural use-local IDs rather than expensive numeric freshening, and treats unconstrained variable-variable matches as constraints that do not create substitution cycles. Concrete observations still bind these variables when enough information is available. This is what lets explicitly annotated higher-order boundaries accept polymorphic values, for example `compose id id "x"`, and lets quantified values satisfy concrete requirements such as `Fn [String] String`. It gives useful polymorphic contracts for explicitly declared/imported View facts. `Exists` supports checked abstraction boundaries. A module can expose a value as "some representation `_repr` plus capabilities over `_repr`": ```text Exists _repr. Pair (Fn [String] _repr) -- constructor (Fn [_repr] String) -- renderer / eliminator ``` This does not make raw Tree Calculus inspection impossible. Unchecked code can always inspect trees. It means checked clients cannot justify representation-specific operations through the View system unless the package exports an appropriate capability or eliminator. This leads to an important distinction for future checked subsets: ```text controlled observation: Bool/List/Maybe/Result/etc. eliminators with Views raw observation: direct tree-shape inspection through triage-like power ``` Useful application code can live mostly in the controlled fragment and receive explicit View validation over lambdas, application, let, and typed eliminators. Low-level library code may still use raw intensionality, but should expose disciplined Views and capabilities above it. Scott-encoded constructors and eliminators are a natural tricu-native representation for these APIs. Tree Calculus terms do not carry intrinsic principal Views, and raw intensional code can invalidate parametric claims. View Contracts are an explicit evidence and contract layer over tricu programs; limited polymorphic Views are supported when they are declared or imported as facts with provenance. The first stdlib annotation island starts with parametric functions that do not inspect representation: ```tri id x@_a =@_a x const x@_a y@_b =@_a x compose f@(Fn [_b] _c) g@(Fn [_a] _b) x@_a =@_c f (g x) ``` Re-export-only modules preserve imported View metadata, so these contracts flow through `prelude` rather than only through direct `base` imports. Functions built on raw `t`/`triage` should enter the checked world through trusted, controlled eliminator contracts rather than by treating arbitrary raw inspection as parametric. ## 5. Guards Guards are ordinary `tricu` values/functions grouped with the Views they refine. Example: ```tri userIdGuard = value : -- ordinary program that validates value UserId = viewGuarded (viewRef "UserId") userIdGuard loadUser id@UserId = ... ``` Guards return the standard checked-runtime protocol: ```tri guardOk value guardFail ``` Guards do not author diagnostics. The checked-exec runner owns guard failure and malformed-guard diagnostics using boundary context from the checked artifact. Guards are injected by the checker. They are not discovered by the runtime as a separate metadata layer. The checking process transforms a view tree into an executable tree with the necessary guard applications inserted. ## 6. View Tree Artifact The primary checker-facing artifact is a view executable term graph. Conceptually: ```text ViewTree version root node id nodes ``` Each node is tagged tree data. Nodes combine executable payloads, view claims, and structural relationships in one graph. Representative node forms: ```text Value node view executableTree Apply node calleeNode argNode expectedOrInferredView Require node requiredView sourceNode External node name view ``` This is not a mandatory final encoding; it is the semantic target. The important property is that executable trees and checking structure are carried together in a single portable artifact. A node may contain opaque executable fields. Those fields are tree terms, but they are not recursively decoded as view-tree nodes or Views unless the node's semantics explicitly says so. View facts may also carry explicit per-fact trust provenance: ```text Checked -- derived by checked lowering / checker validation Trusted -- asserted by a trusted boundary, e.g. a primitive eliminator API Unchecked -- raw or assumed; no parametricity/abstraction guarantee ``` In the portable view-tree envelope this provenance is represented as an optional field on `typedValue` / `typedRequire` facts. In module manifests the same provenance is carried beside the exported View Contract object reference so that imports and re-exports preserve it without relying on module-level convention. Absent provenance is interpreted conservatively as `Unchecked` at use sites. For parametric checked definitions, the frontend now performs a conservative raw-intensionality dependency pass over local definitions. If a definition with scoped View variables depends directly or indirectly on raw `triage` / raw `t` construction, or on an imported `Unchecked` fact, lowering fails and asks the author to route observation through a trusted eliminator boundary. This is intentionally provenance/dependency based; it is not an attempt to decide whether arbitrary Tree Calculus reduction will ever reach rule 3. View facts can be authored as ordinary value-level Tree Calculus metadata under one conventional top-level name: ```text viewFacts = [fact ...] fact = pair exportName (pair provenance view) ``` where `exportName` is a string naming a value exported by the module, `provenance` is `0 = Checked`, `1 = Trusted`, or `2 = Unchecked`, and `view` is the same portable View record used by `view-tree` artifacts. The host evaluates this value and decodes the data schema; it does not infer trust from source syntax, AST shape, module name, or a Haskell-side catalog. The initial trusted eliminator facts are authored this way in clearly separated stdlib `viewFacts` sections: ```text matchBool : forall r. r -> r -> Bool -> r matchMaybe : forall a r. r -> (a -> r) -> Maybe a -> r matchList : forall a r. r -> (a -> List a -> r) -> List a -> r ``` The `base` module provides small `facts*` authoring helpers for this advanced metadata, e.g. `factsFact`, `factsChecked`, `factsTrusted`, `factsUnchecked`, `factsForall`, `factsFn`, `factsVar`, `factsBool`, `factsString`, `factsByte`, `factsUnit`, `factsMaybe`, and `factsList`. These helpers construct ordinary Tree data; authority comes from the exported `viewFacts` value and its explicit provenance tags. Loader validation rejects duplicate fact names and facts for names the module does not export. Initial derived stdlib annotations using this trusted kernel include: ```text maybeMap : forall a b. (a -> b) -> Maybe a -> Maybe b maybeBind : forall a b. Maybe a -> (a -> Maybe b) -> Maybe b maybeOr : forall a. a -> Maybe a -> a ``` Recursive list combinators are currently published as explicit `Trusted` value-level facts rather than `Checked` source annotations, because their bodies pass through raw fixed-point machinery that the conservative parametric taint pass intentionally does not prove safe. This is the stabilized boundary: raw stdlib kernels establish conventions with explicit authority; ordinary checked clients consume those facts rather than re-proving the internals. ```text headMaybe / lastMaybe / nthMaybe append / map / filter / foldl / foldr length / reverse / snoc / count / all? / any? / intersect take / drop / splitAt / concatMap / find / partition / zipWith string/list-byte helpers such as strLength, startsWith?, lines, words ``` ## 7. Checker Semantics The checker is an interpreter over the view tree. For each node it may: 1. validate the node envelope; 2. validate Views referenced by the node; 3. check compatibility between expected and actual Views; 4. recursively check child nodes; 5. inject guards required by guarded Views; 6. produce the executable tree for that node; 7. memoize node results by node id. The root node result is a checked-execution program. In abstract form: ```text checkViewTree : ViewTree -> Result CheckedExec Diagnostic ``` or, in self-hosted terms: ```tri checkViewTree viewTree = ... -- ok checkedExec / err diagnostic ``` ## 8. Compatibility and Guard Injection Structural compatibility is about Views. Guard injection is about producing the checked-execution tree. For example, if a node is required to satisfy: ```tri viewGuarded (viewRef "UserId") userIdGuard ``` then the checker verifies the underlying View relationship and emits executable code that applies `userIdGuard` at the appropriate checked boundary. The checker, not the runtime metadata system, owns this transformation. ## 9. Source Annotations Source annotations are one frontend syntax for producing view-tree nodes. Examples: ```tri Nat = viewRef "Nat" Box a = viewPair (viewRef "Box") a idNat x@Nat =@Nat x idBox x@(Box String) =@(Box String) x ``` Annotations are value-level View expressions. Names such as `Nat` and `Box` are ordinary program values/functions that evaluate to Views. A frontend that supports this syntax should lower the source into a view tree that contains the relevant executable terms, views, and checking structure. The artifact must not depend on source names or on the frontend implementation that produced it. ## 10. Contract Expressions Contract-expression helpers remain useful as authoring/building tools, but they are not the fundamental artifact model. Preferred style for expression-oriented authoring is pipeline-first: ```tri mapBoolStringUse = cFn <| [(viewFn [(viewBool)] viewString) (viewList viewBool)] (viewList viewString) |> cApply (cFn [(viewBool)] viewString) |> cApply (cValue (viewList viewBool)) |> cRequire (viewList viewString) ``` These helpers should be understood as convenient ways to build typed/checkable structure, not as a permanent replacement for view-tree artifacts. ## 11. Artifact Direction The target direction is to make the view tree the canonical checked-program artifact. Older split concepts remain useful internally or during development: ```text tree term view value typed-program node module/export manifest ``` But the durable design should avoid treating contracts as detached facts about a separate program. The portable checker input is the checkable program itself. In short: ```text Do not store code over here and contracts over there. Store a view tree: executable code plus the structure needed to check and guard it. ``` ## 12. IO Interaction Trees `tricu` IO is represented as ordinary interaction-tree data: ```tri io action = pair "tricuIO" (pair version action) pure value = pair 0 value bind action k = pair 1 (pair action k) ``` View Contracts do not change that representation. A checked program may produce an ordinary IO interaction tree, and the existing IO driver can execute it unchanged. For source evaluation with contracts enabled, `tricu eval --io` performs an additional frontend instrumentation pass over visible IO continuations. When a continuation returns a `pure (...)` value that mentions source-annotated functions, the frontend lowers that pure expression into the existing portable checked-exec protocol before returning the next IO action. This means source sugar works for practical checked IO paths such as: ```tri acceptNames xs@(NonEmptyList String) =@String "accepted" main = io (bind (pure []) (xs : pure (acceptNames xs))) ``` and for explicit higher-order boundaries: ```tri useHandler handler@(Fn [(NonEmptyList String)] String) xs@(List String) =@String handler xs main = io (bind (pure []) (xs : pure (useHandler acceptNames xs))) ``` The IO runtime does not perform View inference or guard injection at every step. The source/frontend pass constructs checked-exec boundaries once; the runtime only evaluates the resulting interaction tree. Current limitations: - This is source-visible instrumentation, not whole-program function-flow tracking. - Higher-order guarantees require explicit annotated boundaries. - Raw prebuilt interaction trees, imported executable artifacts, and content-store terms are not automatically re-instrumented unless they pass through this source-lowering path. - The IO action shape itself is only shallowly checkable unless users provide guarded Views for the relevant boundaries. - Continuation result Views are not inferred from external effects; dynamic IO values should cross annotated/guarded boundaries when runtime enforcement is required. Making IO checking more complete is future work. In particular, a future design may validate every continuation-produced action structurally, carry checked wrappers with higher-order function values, or define a portable checked-IO artifact instead of relying on Haskell/frontend source instrumentation. ## 13. Host Independence No part of the core View Tree design is specific to Haskell or to the current implementation. Any producer may emit a view-tree artifact if it follows the portable tree-data encoding. Any checker implementation may consume it if it implements the typed node semantics. The current implementation can produce and consume these artifacts, but it is not the semantic authority. The artifact format and the self-hosted checker semantics are the authority.