h7x4
dcdf36f4dd
- Switch from `cabal2nix` and haskell overlay to `developPackage` - Restructure directories to have more descriptive names - Fix `nix run`
59 lines
2.3 KiB
Markdown
59 lines
2.3 KiB
Markdown
---
|
|
title: "The nix arrow operator"
|
|
keywords: nix, short, language, programming-language
|
|
image: './images/nix_banner.png'
|
|
series: "Nix shorts"
|
|
---
|
|
|
|
There is a specal operator in nix, written as `->`. It is not a [C dereference struct pointer operator][c-deref-struct], nor is it a [haskell function type definition][haskell-function]. It is a boolean operator, which represents the "implies arrow" from [propositional logic][prop-log]. This is especially useful in nix, because of its usage in modules.
|
|
|
|
## The `myService` module
|
|
|
|
Let's say you have made a module for `myService` with two options called `myService.enable`, and `myService.address`. `myService` needs an address in order to work properly. If `myService` is not enabled, the value of `myService.address` doesn't really matter. Set or `null`, the result will be the same either way. If `myService` is enabled however, it is crucial that we report an error if `myService.address` is not set. `myService` can not work without it.
|
|
|
|
In order to make sure that this never happens, we need to assert that this is not the case. This could be done by asserting that this boolean expression is true.
|
|
|
|
`((!myService.enable) || myService.address != null)`
|
|
|
|
or in plain english: "Either myService is not enabled, or the address has to not be null"
|
|
|
|
This is equivalent to this boolean expression:
|
|
|
|
`myService.enable -> myService.address != null`
|
|
|
|
or in plain english: "myService being enabled implies that the address is not null".
|
|
|
|
Asserting these kinds of inter-setting dependencies are common enough in nix modules to provide grounds for having `->` as its own boolean operator.
|
|
|
|
## Full example
|
|
|
|
```nix
|
|
# modules/myService.nix
|
|
{ lib, config }: let
|
|
cfg = config.myService;
|
|
in {
|
|
options = {
|
|
enable = lib.mkEnableOption "myService";
|
|
address = lib.mkOption {
|
|
example = "127.0.0.1";
|
|
description = "The address of myService";
|
|
type = lib.types.string;
|
|
};
|
|
};
|
|
config = {
|
|
# ...
|
|
|
|
assertions = [
|
|
{
|
|
assertion = cfg.enable -> cfg.address != null;
|
|
message = "myService needs an address";
|
|
}
|
|
];
|
|
};
|
|
}
|
|
```
|
|
|
|
[c-deref-struct]: https://www.digitalocean.com/community/tutorials/arrow-operator-c-plus-plus
|
|
[haskell-function]: http://learnyouahaskell.com/functors-applicative-functors-and-monoids
|
|
[prop-log]: https://iep.utm.edu/prop-log/
|