В области математической логики и информатики , известной как теория типов , единичный тип — это тип , который допускает только одно значение (и, следовательно, не может содержать никакой информации). Носитель (базовый набор), связанный с типом единицы, может быть любым одноэлементным набором . Между любыми двумя такими множествами существует изоморфизм , поэтому принято говорить о типе единицы, игнорируя детали ее значения. Можно также рассматривать тип единицы как тип 0- кортежей , т.е. произведение без типов.
Тип модуля — это терминальный объект в категории типов и типизированных функций. Его не следует путать с нулевым или пустым типом , который не допускает никаких значений и является начальным объектом в этой категории. Аналогично, Boolean — это тип с двумя значениями.
Тип unit реализован в большинстве функциональных языков программирования. Тип void , который используется в некоторых императивных языках программирования, выполняет некоторые из своих функций, но поскольку его набор носителей пуст, он имеет некоторые ограничения (как подробно описано ниже).
Некоторые языки программирования предоставляют тип модуля для указания типа результата функции с единственной целью вызвать побочный эффект , а также тип аргумента функции, которая не требует аргументов.
()
и его единственным значением также является ()
, что отражает интерпретацию 0-кортежа.unit
но значение записывается как ()
.Unit
и его единственное значение записывается как ()
.NoneType
который позволяет использовать одно значение None
. В необязательных аннотациях статического типа Python этот тип представлен как None
. [1]Void
or ()
, и его единственное значение также — ()
, что отражает интерпретацию нулевого кортежа.Void
и его единственное значение — null
.struct{}
и его значение struct{}{}
.Null
(единственное значение — null
) и Undefined
(единственное значение — undefined
) являются встроенными типами модулей.Unit
только с одним значением: Unit
объектом.nil
единственный экземпляр класса NilClass
.std::monostate
был добавлен в C++17. До этого можно определить тип пользовательского модуля, используя пустую структуру, например struct empty{}
.В C , C++ , C# , D и PHP используется void
для обозначения функции, которая не возвращает ничего полезного, или функции, не принимающей аргументов. Тип unit в C концептуально похож на пустой struct
, но структура без членов не допускается в спецификации языка C (это разрешено в C++). Вместо этого ' void
' используется таким образом, чтобы имитировать некоторые, но не все свойства типа юнита, как подробно описано ниже. Как и большинство императивных языков, C допускает функции, которые не возвращают значение; они указаны как имеющие тип возврата void. Такие функции называются процедурами в других императивных языках, таких как Паскаль , где между функциями и процедурами проводится синтаксическое различие, а не различие в системе типов.
Первое заметное различие между настоящим типом модуля и типом void заключается в том, что тип модуля всегда может быть типом аргумента функции, но тип void не может быть типом аргумента в C, несмотря на то, что он может быть типом аргумента функции. отображаться как единственный аргумент в списке. Эту проблему лучше всего иллюстрирует следующая программа, которая представляет собой ошибку времени компиляции в C:
недействительный f ( недействительный ) {} недействительный г ( недействительный ) {} int main ( void ) { f ( g ()); // ошибка времени компиляции return 0 ; }
Эта проблема не возникает в большинстве случаев программирования на C, поскольку, поскольку void
тип не несет никакой информации, передавать его в любом случае бесполезно; но он может возникнуть в универсальном программировании , например в шаблонах C++ , где void
его следует рассматривать иначе, чем другие типы. Однако в C++ разрешены пустые классы, поэтому можно реализовать реальный тип модуля; приведенный выше пример становится компилируемым как:
класс unit_type {}; const unit_type the_unit ; unit_type f ( unit_type ) { return the_unit ; } unit_type g ( unit_type ) { return the_unit ; } int main () { f ( g ( the_unit )); вернуть 0 ; }
(Для краткости: в приведенном выше примере нас не беспокоит, the_unit
действительно ли это синглтон ; подробности по этому вопросу см. в шаблоне синглтон .)
Второе заметное отличие состоит в том, что тип void является особенным и никогда не может храниться в типе записи , т. е. в структуре или классе в C/C++. Напротив, тип единицы измерения может храниться в записях функциональных языков программирования, т.е. он может отображаться как тип поля; приведенную выше реализацию типа единицы в C++ также можно сохранить. Хотя эта функция может показаться бесполезной, она позволяет, например, элегантно реализовать набор в виде сопоставления с типом устройства; даже при отсутствии типа модуля набор можно реализовать таким образом, сохраняя для каждого ключа некоторое фиктивное значение другого типа.
В Java Generics параметры типа должны быть ссылочными типами. Тип-оболочка Void
часто используется, когда необходим параметр типа модуля. Хотя этот Void
тип никогда не может иметь экземпляров, он имеет одно значение null
(как и все другие ссылочные типы), поэтому он действует как единичный тип. На практике Math
для этой цели также можно использовать любой другой неинстанционируемый тип, например , поскольку они также имеют ровно одно значение null
.
public static Void f ( Void x ) { return null ; } Public static Void g ( Void x ) { return null ; } public static void main ( String [] args ) { f ( g ( null )); }
Статически типизированные языки присваивают тип каждому возможному выражению. Им необходимо связать тип с нулевым выражением. Тип будет определен для значения null и будет иметь только это значение.
Например, в D можно объявить функции, которые могут возвращать только значение null :
typeof ( null ) returnThatSpecialThing () { return null ; }
null — единственное значение, которое может иметь typeof(null) — тип единицы измерения.