makes icon indicating copy to clipboard operation
makes copied to clipboard

Consider module-system -> typed-functions

Open kamadorueda opened this issue 4 years ago • 8 comments

I was very excited when I originally discovered we can use the NixOS module system for other things beyond configuring NixOS. I found quite simple for being able to configure things with a meere enable = true; and further customize generated code by just giving values to the options

I really think it works great and allows us to achieve modularity, declarative programming, easy to read code. Its problems are more the following:

  • It require non-nix developers to learn an extra thing (how to write modules)
  • Writing can be hard sometimes, even for smart and experienced programmers, particularly when something fails: #742 nixos/nix#3505
  • Not all Makes are modules, so it may feel a little bit of an inconsistency to have modules and units

Instead, I propose to replace the module system with typed functions:

  • Functions are easy to learn
  • Functions that replace the module system semantics would not have infinite recursion problems
  • Functions fail gracefully more often than module systems, a.k.a. with a proper trace-back that points where the error happened
  • Typed functions are typed, same as the module system

So we would write makes.nix as follows:

{
  outputs = {
    "/formatMarkdown/my-code" = formatMarkdown {
       src = "/my/code";
     };
  };
}

this will also make easier to organize code to prepare for future releases of nix, a.k.a. https://github.com/fluidattacks/makes/milestone/2

kamadorueda avatar Oct 15 '21 15:10 kamadorueda

another option could be not having a makes.nix at all, and configuring everything under /makes, this way users don't have to write the full path, just create a directory structure. Maybe some things like the cache configuration can be implemented in /makes/config.nix

kamadorueda avatar Oct 15 '21 16:10 kamadorueda

In general after solving this issue Makes will be a more welcoming place for adoption

kamadorueda avatar Oct 15 '21 16:10 kamadorueda

what exactly do you mean by "type-functions" seeing as Nix has no builtin type system. Do you mean a system similar to what the Nix module system employs, i.e. runtime type checks?

nrdxp avatar Oct 15 '21 19:10 nrdxp

type-functions

typed-functions, function with types

i.e. runtime type checks?

Yes, exactly this, I don't know how that would be implemented but nixpkgs.lib.types expose function that perform the validation logic and return a boolean. Maybe we can leverage that or build our own. It should be simple anyway as we use basic types most of the times

kamadorueda avatar Oct 15 '21 19:10 kamadorueda

typed-functions, function with types

That was just a typo, I know what you intended to say :sweat_smile: Thanks for clarification.

There is lib.types.functionTo which will verify the type that a function evaluates to, but, depending on the function, it can be an expensive check since it actually calls the function to verify this.

nrdxp avatar Oct 15 '21 19:10 nrdxp

There is lib.types.functionTo which will verify the type that a function evaluates to, but, depending on the function, it can be an expensive check since it actually calls the function to verify this.

Yeah, we would not use that then, that one is expensive because it verifies the function return value, we don't need to verify the return value in this case as we are the ones who specify it, just the function arguments are user-supplied data subject to type verification

kamadorueda avatar Oct 15 '21 20:10 kamadorueda

That might be a tricky problem to solve then :thinking: It might be useful upstream too if we find a solution though

nrdxp avatar Oct 15 '21 20:10 nrdxp

let
  types.int = elem: builtins.typeOf elem == "int";

  func = { age }:
    assert types.int age;
    "Your age is ${builtins.toString age}";
in
func { age = "13"; }
error: while evaluating 'func' at /data/gitlab/fluidattacks/product/example.nix:4:10, called from /data/gitlab/fluidattacks/product/example.nix:8:1:
assertion ((types).int  age) failed at /data/gitlab/fluidattacks/product/example.nix:5:5

we could improve the error message using builtins.abort instead of assert

kamadorueda avatar Oct 15 '21 21:10 kamadorueda