2.7 KiB
2.7 KiB
例
この章には、仕様を説明するための例を置く。
基本的な設定スキーマ
Host = IPv4Address;
Port = Int & >= 1 & <= 65535;
NarrowedPort = Port & > 443;
MyConfig = {
host = Host;
port = NarrowedPort default 8080;
feature_hoge = {
enable = Bool default true;
fuga = Int default 10;
};
};
NewConfig = MyConfig & {
host = "127.0.0.1";
port = 8000;
};
disabled_config = NewConfig & {
feature_hoge.enable = false;
};
enabled_config = NewConfig;
配列スキーマ
Services = [...{
name = String;
port = Int default 8080;
}];
[
{ name = "api"; },
{ name = "worker"; port = 9000; },
] as Services
抽象配列には要素制約が必須である。
この例では、1 番目の要素の port は 8080 に materialize される。
連想配列と範囲絞り込み
Service = {
port = Int;
enabled = Bool default true;
};
services = {
api = { port = 8080; };
worker = { port = 8081; enabled = false; };
} as {...Service};
api と worker は任意の key であり、それぞれの value は Service より狭い範囲へ絞り込まれる。
as の結果では api.enabled は abstract のまま残り、最終的に結果全体を materialize した時点で default の true が使われる。
関数と制約
let
Port = Int & >= 1 & <= 65535;
add_offset = (base: Port, offset: Int) => base + offset;
in
add_offset(8000, 80)
評価結果:
8080
match
(
input_a: {
hoge = Int & >= 0;
},
input_b: {
fuga = 20;
}
) =>
let
inputs = {
a = input_a;
b = input_b;
};
in
{
foo = match inputs.a.hoge {
>= 20: {
value = 200;
};
>= 10: {
value = 100;
};
_: {
value = 300;
};
};
}
match は上から順に評価されるため、広い条件より狭い条件を先に書く。
deep patch
Base = {
feature_hoge = {
enable = Bool default true;
fuga = Int default 10;
};
};
Patched = Base // {
feature_hoge.enable = false;
};
Patched は以下に相当する。
{
feature_hoge = {
enable = false;
fuga = Int default 10;
};
}
循環 import
# main.n
{
schema = {
hoge = String;
};
result = (import ./func.n)(schema);
}
# func.n
(input: (import ./main.n).schema) =>
{
# ...
}
func.n は main.n を import しているが、参照しているのは main.schema である。
main.schema が main.result に依存していなければ、この循環 import は成立する。