Designing modules and libraries
A good tulam library exposes semantic contracts while keeping representation, provider, and incidental dependencies private.
Start with a narrow module surface
Use explicit export lists. Hide constructors with opaque type when clients should preserve an invariant through public functions. Prefer explicit imports so dependencies remain visible during review.
Choose the right abstraction
- Use an algebraic data type for a closed family of cases.
- Use a structural record for open field compatibility.
- Use a nominal class for dynamic dispatch and extension.
- Use a structure/algebra for reusable evidence.
- Use a morphism/bridge for a directional typed relationship.
- Use an effect for a capability whose implementation may vary.
Combining these is normal; forcing one mechanism to imitate all others usually weakens the contract.
State public types clearly
Exported functions should normally state parameters, result types, effect rows, and requires constraints. Inference remains valuable inside implementations. Dependent indices should represent facts callers care about, not implementation incidents.
Coherence and instance ownership
Unnamed implicit evidence must have one coherent choice. Put canonical instances near the type or algebra ownership boundary. Use named instance tags for intentional alternatives instead of relying on import order.
Separate semantics and providers
Declare the portable operation once. Put native, managed, browser, or accelerator implementations in target blocks. A provider must refine the canonical contract and cannot create a target-only public API.
Document status honestly
Examples should say when a normative feature has a known implementation gap. Do not replace it with legacy syntax or document parser quirks as alternatives. Link programmer-visible rules to the Language Reference and volatile status to the Implementation Plan.
Compatibility
Changing an exported type, effect row, constraint, instance choice, law, class hierarchy, or representation can be a source or semantic compatibility change. The future typed-interface phase will make these boundaries machine-checkable; today, disciplined exports and conformance programs provide the foundation.
Common mistakes
Avoid exporting representation constructors accidentally, scattering competing canonical instances, leaking backend modules through portable APIs, or changing an effect row under the assumption that it is merely implementation detail.
Recap
A durable library states a narrow semantic contract, owns its evidence choices, and keeps representation and provider refinements behind that contract.