Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Motivation

Adios aims to be a radically simple alternative to the NixOS module system that solves many of it's design problems. Modules are contracts that are typed using the Korora type system.

NixOS module system problems

  • Lack of flexibility

NixOS modules aren't reusable outside of a NixOS context. The goal is to have modules that can be reused just as easily on a MacOS machine as in a Linux development shell.

  • Global namespace

The NixOS module system is a single global namespace where any module can affect any other module.

  • Resource overhead

Because of how NixOS modules are evaluated, each evaluation has no memoisation from a previous one. This has the effect of very high memory usage.

Adios modules are designed to take advantage of lazy evaluation and memoisation.

Concept

Modules

Module definition

Adios module definitions are plain Nix attribute sets.

Module loading

The module definition then needs to be loaded by the adios loader function:

adios {
  name = "my-module";
}

Module loading is responsible for

  • Wrapping the module definition with a type checker

    Module definitions are strictly typed and checked.

  • Wrapping of module definitions impl function that provides type checking.

Callable modules

Callable modules are modules with an impl function that takes an attrset with their arguments defined in options:

{ types }:
{
  name = "callable-module";

  options = {
    foo = {
      type = types.string;
      default = "foo";
    };
  };

  impl = args: {
    # Evaluating someValue.bar will type check args.foo
    someValue.bar = args.foo;
  };
}

Note that module returns are not type checked. It is expected to pass the return value of a module into another module until you have a value that can be consumed.

Laziness

Korora does eager evaluation when type checking values. Adios module type checking however is lazily, with some caveats:

  • Each option, type, test, etc returned by a module are checked on-access

  • When calling a module each passed option is checked lazily

But defined struct's, listOf etc thunks will be forced. It's best for options definitions to contain a minimal interface to minimize the overhead of eager evaluation.

Modules

Right now the only module that ship with adios is a partial reimplementation of treefmt-nix. This module is a great place to start to get an idea for how to work with adios modules.

I (@adisbladis) use adios in my private configuration repository with even more modules defined, but they are too highly custom to me to be suitable for inclusion.