Parametric Aspects
Provider-level parametric
Section titled “Provider-level parametric”Providers inside provides can be curried functions. The outer function takes user arguments; the inner function (if needed) takes { class, aspect-chain }:
flake.aspects = { aspects, ... }: { base.provides.user = userName: { nixos.users.users.${userName}.isNormalUser = true; }; server = { includes = [ (aspects.base._.user "bob") ]; nixos = { }; };};Resolving server for "nixos" produces imports containing { users.users.bob.isNormalUser = true; }.
Top-level parametric
Section titled “Top-level parametric”Top-level aspects can also be curried. The function takes named arguments and returns an aspect:
flake.aspects = { aspects, ... }: { greeter = { message }: { nixos.greeting = message; }; host = { includes = [ (aspects.greeter { message = "hello"; }) ]; nixos = { }; };};The type system (nix/types.nix) distinguishes between:
- Direct providers:
{ class, aspect-chain } → aspect(1-2 named args:classand/oraspect-chain) - Curried providers:
anything → provider(other function signatures)
A curried provider is invoked by the user at inclusion time. Its return value must be either another provider function or a direct aspect attrset.
Combining with context
Section titled “Combining with context”A parametric provider can return a context-aware function:
provides.themed = theme: { class, aspect-chain }: { ${class}.theme = "${theme}-for-${(lib.last aspect-chain).name}"; };This is a three-level chain: user args → context → aspect config.