Lie-Typing
Lie-Typing
Tutorial: Lie-TypingSee also: Lazy Construction, API: instantiate
The Core Insight
Python's type system has no way to say "this is a DictConfig that materializes
into a T when passed to instantiate." The real runtime type is DictConfig;
the useful static type is T.
Laco resolves the tension with an intentional mismatch. L.call(nn.Linear)(...)
is declared to return nn.Linear. The IDE and type-checkers accept this
declaration, but at runtime it returns a DictConfig. This mismatch is load-
bearing. Without it, nested composition collapses to Any after the first
level.
The Six Constructs
| Construct | Static type | Runtime type | Use case |
|---|---|---|---|
L.call(T)(...) | T | DictConfig | Lazy class construction |
L.partial(T)(...) | T | DictConfig | Deferred partial application |
L.just(v) | type(v) | DictConfig | Wrap an existing value |
L.required[T]() | T | DictConfig | Mandatory placeholder |
L.slot(G) | G | DictConfig | Group placeholder in schema |
L.chosen(G) | G | DictConfig | In-body cross-reference |
Where the Mismatch is Enforced
Laco enforces the mismatch at two system boundaries.
laco.loadaccepts only Laco nodes produced by the six constructs above, plus primitives. It rejects plain Python objects that are not node instances.laco.instantiateconvertsDictConfigback to the genuineT, both at runtime and in its static signature.
Between those two boundaries, type-checked code sees T. Code at runtime
sees DictConfig. The mismatch matters only inside config files, where you
construct nodes. It does not matter inside training code, where you consume
them after instantiate.
LazyObject[T]
When a function receives a config node that will be instantiated inside it,
annotate the parameter with LazyObject[T]:
from laco import LazyObject, instantiate
def build(model_cfg: LazyObject[nn.Module]) -> nn.Module:
return instantiate(model_cfg)
LazyObject[T] exists only for type-checking. It is an alias for
DictConfig at runtime. The instantiate overload LazyObject[T] -> T
makes the return type concrete.
LACO_STRICT_NODES
During development you can set LACO_STRICT_NODES=1 to make DictConfig
nodes raise AttributeError on attribute access that isn't a config key.
This catches accidental use of a node as if it were the real object.
LACO001 Lint Rule
laco-lint emits LACO001 when it detects attribute access on a value
annotated as a Laco node type. Add # noqa: LACO001 to suppress an
intentional access (e.g. introspecting ._metadata).