mirror of
https://github.com/ilyakooo0/nixpkgs.git
synced 2024-12-26 04:43:09 +03:00
NixOS manual: add module option types doc (#18525)
This commit is contained in:
parent
3e7bb6579b
commit
b32252ddfa
@ -31,9 +31,9 @@ options = {
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>type</varname></term>
|
<term><varname>type</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>The type of the option (see below). It may be omitted,
|
<para>The type of the option (see <xref linkend='sec-option-types' />).
|
||||||
but that’s not advisable since it may lead to errors that are
|
It may be omitted, but that’s not advisable since it may lead to errors
|
||||||
hard to diagnose.</para>
|
that are hard to diagnose.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
@ -65,86 +65,4 @@ options = {
|
|||||||
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>Here is a non-exhaustive list of option types:
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>types.bool</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>A Boolean.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>types.int</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>An integer.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>types.str</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>A string.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>types.lines</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>A string. If there are multiple definitions, they are
|
|
||||||
concatenated, with newline characters in between.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>types.path</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>A path, defined as anything that, when coerced to a
|
|
||||||
string, starts with a slash. This includes derivations.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>types.package</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>A derivation (such as <literal>pkgs.hello</literal>) or a
|
|
||||||
store path (such as
|
|
||||||
<filename>/nix/store/1ifi1cfbfs5iajmvwgrbmrnrw3a147h9-hello-2.10</filename>).</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>types.listOf</varname> <replaceable>t</replaceable></term>
|
|
||||||
<listitem>
|
|
||||||
<para>A list of elements of type <replaceable>t</replaceable>
|
|
||||||
(e.g., <literal>types.listOf types.str</literal> is a list of
|
|
||||||
strings). Multiple definitions are concatenated together.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term>
|
|
||||||
<listitem>
|
|
||||||
<para>A set of elements of type <replaceable>t</replaceable>
|
|
||||||
(e.g., <literal>types.attrsOf types.int</literal> is a set of
|
|
||||||
name/value pairs, the values being integers).</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>types.nullOr</varname> <replaceable>t</replaceable></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Either the value <literal>null</literal> or something of
|
|
||||||
type <replaceable>t</replaceable>.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
You can also create new types using the function
|
|
||||||
<varname>mkOptionType</varname>. See
|
|
||||||
<filename>lib/types.nix</filename> in Nixpkgs for details.</para>
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
394
nixos/doc/manual/development/option-types.xml
Normal file
394
nixos/doc/manual/development/option-types.xml
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
<section xmlns="http://docbook.org/ns/docbook"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||||
|
version="5.0"
|
||||||
|
xml:id="sec-option-types">
|
||||||
|
|
||||||
|
<title>Options Types</title>
|
||||||
|
|
||||||
|
<para>Option types are a way to put constraints on the values a module option
|
||||||
|
can take.
|
||||||
|
Types are also responsible of how values are merged in case of multiple
|
||||||
|
value definitions.</para>
|
||||||
|
<section><title>Basic Types</title>
|
||||||
|
|
||||||
|
<para>Basic types are the simplest available types in the module system.
|
||||||
|
Basic types include multiple string types that mainly differ in how
|
||||||
|
definition merging is handled.</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.bool</varname></term>
|
||||||
|
<listitem><para>A boolean, its values can be <literal>true</literal> or
|
||||||
|
<literal>false</literal>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.int</varname></term>
|
||||||
|
<listitem><para>An integer.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.path</varname></term>
|
||||||
|
<listitem><para>A filesystem path, defined as anything that when coerced to
|
||||||
|
a string starts with a slash. Even if derivations can be considered as
|
||||||
|
path, the more specific <literal>types.package</literal> should be
|
||||||
|
preferred.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.package</varname></term>
|
||||||
|
<listitem><para>A derivation or a store path.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para>String related types:</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.str</varname></term>
|
||||||
|
<listitem><para>A string. Multiple definitions cannot be
|
||||||
|
merged.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.lines</varname></term>
|
||||||
|
<listitem><para>A string. Multiple definitions are concatenated with a new
|
||||||
|
line <literal>"\n"</literal>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.commas</varname></term>
|
||||||
|
<listitem><para>A string. Multiple definitions are concatenated with a comma
|
||||||
|
<literal>","</literal>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.envVar</varname></term>
|
||||||
|
<listitem><para>A string. Multiple definitions are concatenated with a
|
||||||
|
collon <literal>":"</literal>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.separatedString</varname>
|
||||||
|
<replaceable>sep</replaceable></term>
|
||||||
|
<listitem><para>A string with a custom separator
|
||||||
|
<replaceable>sep</replaceable>, e.g. <literal>types.separatedString
|
||||||
|
"|"</literal>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section><title>Composed Types</title>
|
||||||
|
|
||||||
|
<para>Composed types allow to create complex types by taking another type(s)
|
||||||
|
or value(s) as parameter(s).
|
||||||
|
It is possible to compose types multiple times, e.g. <literal>with types;
|
||||||
|
nullOr (enum [ "left" "right" ])</literal>.</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.listOf</varname> <replaceable>t</replaceable></term>
|
||||||
|
<listitem><para>A list of <replaceable>t</replaceable> type, e.g.
|
||||||
|
<literal>types.listOf int</literal>. Multiple definitions are merged
|
||||||
|
with list concatenation.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term>
|
||||||
|
<listitem><para>An attribute set of where all the values are of
|
||||||
|
<replaceable>t</replaceable> type. Multiple definitions result in the
|
||||||
|
joined attribute set.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.loaOf</varname> <replaceable>t</replaceable></term>
|
||||||
|
<listitem><para>An attribute set or a list of <replaceable>t</replaceable>
|
||||||
|
type. Multiple definitions are merged according to the
|
||||||
|
value.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.loeOf</varname> <replaceable>t</replaceable></term>
|
||||||
|
<listitem><para>A list or an element of <replaceable>t</replaceable> type.
|
||||||
|
Multiple definitions are merged according to the
|
||||||
|
values.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.nullOr</varname> <replaceable>t</replaceable></term>
|
||||||
|
<listitem><para><literal>null</literal> or type
|
||||||
|
<replaceable>t</replaceable>. Multiple definitions are merged according
|
||||||
|
to type <replaceable>t</replaceable>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.uniq</varname> <replaceable>t</replaceable></term>
|
||||||
|
<listitem><para>Ensures that type <replaceable>t</replaceable> cannot be
|
||||||
|
merged. It is used to ensure option definitions are declared only
|
||||||
|
once.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.enum</varname> <replaceable>l</replaceable></term>
|
||||||
|
<listitem><para>One element of the list <replaceable>l</replaceable>, e.g.
|
||||||
|
<literal>types.enum [ "left" "right" ]</literal>. Multiple definitions
|
||||||
|
cannot be merged</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.either</varname> <replaceable>t1</replaceable>
|
||||||
|
<replaceable>t2</replaceable></term>
|
||||||
|
<listitem><para>Type <replaceable>t1</replaceable> or type
|
||||||
|
<replaceable>t2</replaceable>, e.g. <literal>with types; either int
|
||||||
|
str</literal>. Multiple definitions cannot be
|
||||||
|
merged.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>types.submodule</varname> <replaceable>o</replaceable></term>
|
||||||
|
<listitem><para>A set of sub options <replaceable>o</replaceable>.
|
||||||
|
<replaceable>o</replaceable> can be an attribute set or a function
|
||||||
|
returning an attribute set. Submodules are used in composed types to
|
||||||
|
create modular options. Submodule are detailed in <xref
|
||||||
|
linkend='section-option-types-submodule' />.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section xml:id='section-option-types-submodule'><title>Submodule</title>
|
||||||
|
|
||||||
|
<para>Submodule is a very powerful type that defines a set of sub-options that
|
||||||
|
are handled like a separate module.
|
||||||
|
It is especially interesting when used with composed types like
|
||||||
|
<literal>attrsOf</literal> or <literal>listOf</literal>.</para>
|
||||||
|
|
||||||
|
<para>The submodule type take a parameter <replaceable>o</replaceable>, that
|
||||||
|
should be a set, or a function returning a set with an
|
||||||
|
<literal>options</literal> key defining the sub-options.
|
||||||
|
The option set can be defined directly (<xref linkend='ex-submodule-direct'
|
||||||
|
/>) or as reference (<xref linkend='ex-submodule-reference' />).</para>
|
||||||
|
|
||||||
|
<para>Submodule option definitions are type-checked accordingly to the options
|
||||||
|
declarations. It is possible to declare submodule options inside a submodule
|
||||||
|
sub-options for even higher modularity.</para>
|
||||||
|
|
||||||
|
<example xml:id='ex-submodule-direct'><title>Directly defined submodule</title>
|
||||||
|
<screen>
|
||||||
|
options.mod = mkOption {
|
||||||
|
name = "mod";
|
||||||
|
description = "submodule example";
|
||||||
|
type = with types; listOf (submodule {
|
||||||
|
options = {
|
||||||
|
foo = mkOption {
|
||||||
|
type = int;
|
||||||
|
};
|
||||||
|
bar = mkOption {
|
||||||
|
type = str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};</screen></example>
|
||||||
|
|
||||||
|
<example xml:id='ex-submodule-reference'><title>Submodule defined as a
|
||||||
|
reference</title>
|
||||||
|
<screen>
|
||||||
|
let
|
||||||
|
modOptions = {
|
||||||
|
options = {
|
||||||
|
foo = mkOption {
|
||||||
|
type = int;
|
||||||
|
};
|
||||||
|
bar = mkOption {
|
||||||
|
type = int;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
options.mod = mkOption {
|
||||||
|
description = "submodule example";
|
||||||
|
type = with types; listOf (submodule modOptions);
|
||||||
|
};</screen></example>
|
||||||
|
|
||||||
|
|
||||||
|
<section><title>Composed with <literal>listOf</literal></title>
|
||||||
|
|
||||||
|
<para>When composed with <literal>listOf</literal>, submodule allows multiple
|
||||||
|
definitions of the submodule option set.</para>
|
||||||
|
|
||||||
|
<example xml:id='ex-submodule-listof-declaration'><title>Declaration of a list
|
||||||
|
of submodules</title>
|
||||||
|
<screen>
|
||||||
|
options.mod = mkOption {
|
||||||
|
description = "submodule example";
|
||||||
|
type = with types; listOf (submodule {
|
||||||
|
options = {
|
||||||
|
foo = mkOption {
|
||||||
|
type = int;
|
||||||
|
};
|
||||||
|
bar = mkOption {
|
||||||
|
type = str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};</screen></example>
|
||||||
|
|
||||||
|
<example xml:id='ex-submodule-listof-definition'><title>Definition of a list of
|
||||||
|
submodules</title>
|
||||||
|
<screen>
|
||||||
|
config.mod = [
|
||||||
|
{ foo = 1; bar = "one"; }
|
||||||
|
{ foo = 2; bar = "two"; }
|
||||||
|
];</screen></example>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<section><title>Composed with <literal>attrsOf</literal></title>
|
||||||
|
|
||||||
|
<para>When composed with <literal>attrsOf</literal>, submodule allows multiple
|
||||||
|
named definitions of the submodule option set.</para>
|
||||||
|
|
||||||
|
<example xml:id='ex-submodule-attrsof-declaration'><title>Declaration of
|
||||||
|
attribute sets of submodules</title>
|
||||||
|
<screen>
|
||||||
|
options.mod = mkOption {
|
||||||
|
description = "submodule example";
|
||||||
|
type = with types; attrsOf (submodule {
|
||||||
|
options = {
|
||||||
|
foo = mkOption {
|
||||||
|
type = int;
|
||||||
|
};
|
||||||
|
bar = mkOption {
|
||||||
|
type = str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};</screen></example>
|
||||||
|
|
||||||
|
<example xml:id='ex-submodule-attrsof-definition'><title>Declaration of
|
||||||
|
attribute sets of submodules</title>
|
||||||
|
<screen>
|
||||||
|
config.mod.one = { foo = 1; bar = "one"; };
|
||||||
|
config.mod.two = { foo = 2; bar = "two"; };</screen></example>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section><title>Extending types</title>
|
||||||
|
|
||||||
|
<para>Types are mainly characterized by their <literal>check</literal> and
|
||||||
|
<literal>merge</literal> functions.</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>check</varname></term>
|
||||||
|
<listitem><para>The function to type check the value. Takes a value as
|
||||||
|
parameter and return a boolean.
|
||||||
|
It is possible to extend a type check with the
|
||||||
|
<literal>addCheck</literal> function (<xref
|
||||||
|
linkend='ex-extending-type-check-1' />), or to fully override the
|
||||||
|
check function (<xref linkend='ex-extending-type-check-2' />).</para>
|
||||||
|
|
||||||
|
<example xml:id='ex-extending-type-check-1'><title>Adding a type check</title>
|
||||||
|
<screen>
|
||||||
|
byte = mkOption {
|
||||||
|
description = "An integer between 0 and 255.";
|
||||||
|
type = addCheck (x: x >= 0 && x <= 255) types.int;
|
||||||
|
};</screen></example>
|
||||||
|
|
||||||
|
<example xml:id='ex-extending-type-check-2'><title>Overriding a type
|
||||||
|
check</title>
|
||||||
|
<screen>
|
||||||
|
nixThings = mkOption {
|
||||||
|
description = "words that start with 'nix'";
|
||||||
|
type = types.str // {
|
||||||
|
check = (x: lib.hasPrefix "nix" x)
|
||||||
|
};
|
||||||
|
};</screen></example>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>merge</varname></term>
|
||||||
|
<listitem><para>Function to merge the options values when multiple values
|
||||||
|
are set.
|
||||||
|
The function takes two parameters, <literal>loc</literal> the option path as a
|
||||||
|
list of strings, and <literal>defs</literal> the list of defined values as a
|
||||||
|
list.
|
||||||
|
It is possible to override a type merge function for custom
|
||||||
|
needs.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section><title>Custom Types</title>
|
||||||
|
|
||||||
|
<para>Custom types can be created with the <literal>mkOptionType</literal>
|
||||||
|
function.
|
||||||
|
As type creation includes some more complex topics such as submodule handling,
|
||||||
|
it is recommended to get familiar with <filename
|
||||||
|
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/types.nix">types.nix</filename>
|
||||||
|
code before creating a new type.</para>
|
||||||
|
|
||||||
|
<para>The only required parameter is <literal>name</literal>.</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>name</varname></term>
|
||||||
|
<listitem><para>A string representation of the type function name, name
|
||||||
|
usually changes accordingly parameters passed to
|
||||||
|
types.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>check</varname></term>
|
||||||
|
<listitem><para>A function to type check the definition value. Takes the
|
||||||
|
definition value as a parameter and returns a boolean indicating the
|
||||||
|
type check result, <literal>true</literal> for success and
|
||||||
|
<literal>false</literal> for failure.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>merge</varname></term>
|
||||||
|
<listitem><para>A function to merge multiple definitions values. Takes two
|
||||||
|
parameters:</para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable>loc</replaceable></term>
|
||||||
|
<listitem><para>The option path as a list of strings, e.g.
|
||||||
|
<literal>["boot" "loader "grub"
|
||||||
|
"enable"]</literal>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable>defs</replaceable></term>
|
||||||
|
<listitem><para>The list of sets of defined <literal>value</literal>
|
||||||
|
and <literal>file</literal> where the value was defined, e.g.
|
||||||
|
<literal>[ { file = "/foo.nix"; value = 1; } { file = "/bar.nix";
|
||||||
|
value = 2 } ]</literal>. The <literal>merge</literal> function
|
||||||
|
should return the merged value or throw an error in case the
|
||||||
|
values are impossible or not meant to be merged.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>getSubOptions</varname></term>
|
||||||
|
<listitem><para>For composed types that can take a submodule as type
|
||||||
|
parameter, this function generate sub-options documentation. It takes
|
||||||
|
the current option prefix as a list and return the set of sub-options.
|
||||||
|
Usually defined in a recursive manner by adding a term to the prefix,
|
||||||
|
e.g. <literal>prefix: elemType.getSubOptions (prefix ++
|
||||||
|
[<replaceable>"prefix"</replaceable>])</literal> where
|
||||||
|
<replaceable>"prefix"</replaceable> is the newly added
|
||||||
|
prefix.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>getSubModules</varname></term>
|
||||||
|
<listitem><para>For composed types that can take a submodule as type
|
||||||
|
parameter, this function should return the type parameters submodules.
|
||||||
|
If the type parameter is called <literal>elemType</literal>, the
|
||||||
|
function should just recursively look into submodules by returning
|
||||||
|
<literal>elemType.getSubModules;</literal>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>substSubModules</varname></term>
|
||||||
|
<listitem><para>For composed types that can take a submodule as type
|
||||||
|
parameter, this function can be used to substitute the parameter of a
|
||||||
|
submodule type. It takes a module as parameter and return the type with
|
||||||
|
the submodule options substituted. It is usally defined as a type
|
||||||
|
function call with a recursive call to
|
||||||
|
<literal>substSubModules</literal>, e.g for a type
|
||||||
|
<literal>composedType</literal> that take an <literal>elemtype</literal>
|
||||||
|
type parameter, this function should be defined as <literal>m:
|
||||||
|
composedType (elemType.substSubModules m)</literal>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</section>
|
@ -176,6 +176,7 @@ in {
|
|||||||
</example>
|
</example>
|
||||||
|
|
||||||
<xi:include href="option-declarations.xml" />
|
<xi:include href="option-declarations.xml" />
|
||||||
|
<xi:include href="option-types.xml" />
|
||||||
<xi:include href="option-def.xml" />
|
<xi:include href="option-def.xml" />
|
||||||
<xi:include href="meta-attributes.xml" />
|
<xi:include href="meta-attributes.xml" />
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user