Пустое: множество и коробка

Пустое множество принадлежит к набору фундаментальных объектов современной математики. И не только математики: в чистой философии – значение пустого множества едва ли не выше. Поэтому-то постоянно множатся и роли, которые пустое множество играет в куда более прикладных областях, чем теоретическая математика и философия: в информационных технологиях, да и в технике вообще.

Главное свойство пустого множества в том, что такое множество – единственно. То есть, у нас могут быть множества, собранные из разных объектов, но пустое множество – всегда одинаковое. Более того – это одно и то же множество, вне зависмости от “объектов” и типов. Пустое множество ананасов совпадает с пустым множеством апельсинов по слишком многим характеристикам, чтобы считать, что множества ананасов и апельсинов “пусты” разным образом, как и множество фруктов вообще.

Но, конечно, полностью отказаться от того, что “существуют” и пустое множество апельсинов, и пустое множество ананасов – довольно трудно: вот, только что была введена некоторая различительная окраска – ананасы против апельсинов. Например, если для приготовления блюда требуется ананас, то отсутствие апельсина – никак на кулинарную ситуацию не влияет, тогда как нехватка ананаса делает приготовление невозможным. Однако пустота тут, как концепция, общая. Да, нужно различить понятия “пустота” (“тип”) и “быть пустым” (“стрелка”), но стоит поднять пустоту в ничто, как начинает играть тот фактор, что и ничто, в представлении, бывает белое и чёрное.

Особенности естественного языка, позволяющие оборачивать отсутствие элементов в пустом множестве в размытое значение слова “ничего”, создают тем самым возможность для построения разных силлогизмов из пустого множества. Наверное, самый известный из них – про бутерброд (в вольном переводе): “Что лучше, чем вечное счастье? Ничего! Однако, один бутерброд – заведомо лучше, чем ничего. Следовательно – бутерброд лучше вечного счастья” (R. Smullyan/D. Darling). Здесь, естественно, объяснение в том, что в первой части описывается отсутствие объектов, которые лучше данного: таких объектов, утверждается, пустое множество; а потом, на бутербродном шаге, сравнение производится в обратную сторону: бутерброд заведомо лучше состояния, когда бутерброда нет (не отсутствия объектов, а самого пустого множества). То есть, это разные операции, но то, что пустое множество всего одно, позволяет подменять одну операцию другой.

Например, мне однажды переслали распечатку пары значений вывода утилиты sha256sum, на вход которой подавался результат работы модуля ec из пакета openssl (через “пайп” в консоли). При этом в openssl направлялись два разных файла. Утверждалось, что эти два входных файла содержат одинаковые данные, но только записаны данные в разной форме. Почему? Потому, что равны результаты sha256sum от выдачи openssl. Значения sha256sum, действительно, были равны, несмотря на то, что в openssl передавались разные файлы с разными именами.

Что же произошло на самом деле? Вот что. Утилита sha256sum считает значение хеш-функции SHA-256 от входных данных. Здесь на вход sha256sum поступал вывод openssl ec. Но, ещё раз, если значения равны, то, видимо, тогда и входные файлы содержат одинаковые данные? Нет – одинаковым тут является вывод openssl ec: дело в том, что оба входных файла имели неверный формат, поэтому модуль ec не мог их разобрать и печатал сообщение об ошибке, однако в стандартный вывод – писал пустое множество байтов; то есть, ничего не писал, проще говоря. А значения SHA-256 совпали потому, что на вход хеш-функции поступило пустое множество. А оно – одинаковое, вне зависимости от того, как именно сломался каждый из входных файлов.

Множества, состоящие из элементов разных типов, могут не сочетаться по типам, но пустое множество – сочетается со всеми типами. Когда нет апельсинов и ананасов, шестерней и транзисторов – то, с одной стороны, нет вещей разных типов, но, с другой стороны, общим тут является то, что их нет. Это сплошь и рядом используется в языках программирования.

Скажем, пустое множество возвращается в качестве признака того, что функция завершилась с ошибкой: это хорошо известный объект, обозначаемый nil, null, “” – ещё как-то. Обратите внимание, что значение null оказывается чем-то вроде пустоты, которая может быть помещена в коробку (да, именно так). Но null – это ещё не пустая коробка, как ни странно. В программировании, чтобы null стал “пустой коробкой”, этот null придётся как-то дополнительно трактовать: предположим, использвать null как указатель и попробовать обратиться по его значению (выполнить “дереференс”). Ошибочное толкование пустого множества в случае null и программного кода регулярно приводит к возникновению уязвимостей в ПО, в том числе, в весьма неочевидных случаях.

Современное обозначение для пустого множества – ∅ – появилось относительно недавно, в 30-х годах прошлого века. Но вполне возможно, что саму концепцию систематическим образом впервые строил Джордж Буль, в 1847 году. Впрочем, соответствующая концепция у Буля относится к логике и больше похожа на противопоставление “ничего” – которое есть “нуль”, 0, – “всему”, единице, 1.

Есть более интересное развитие определения: через количество объектов, которые не “само-эквивалентны” (Готлоб Фреге). Здесь “само-эквивалентность” – это обобщение свойства рефлексивности, то есть, когда A = A по свойствам операции, а именно, каждый объект эквивалентен самому себе. Тогда пустое множество – это те объекты, которые не эквивалентны самим себе. Казалось бы – таких объектов просто нет. Но чтобы заявить о том, что чего-то нет, придётся определить это “что-то”, чтобы описать и проотрицать существование, и на этом пути магу легко попасть в ловушку: попытка определения того, чего нет, введение типов, может вызвать данный “зомби-объект” к существованию – он, внезапно, “станет быть” или “будет есть” – как там правильно? А вот способ “не-само-эквивалентных” объектов – позволяет выполнить такое определение без излишней типизации и “зомби”. Ну, в каких-то пределах. Так, в DNSSEC подписывается цифровой подписью факт отсутствия записи – делается это при помощи погружения “отсутствия” в искусственный “пустой интервал” между соседними существующими DNS-записями, иногда такое погружение происходит замысловатым образом.

Не так уж редко используется и свойство пустого множества быть невозможным событием. Как известно, вероятность невозможного события, в каком-то смысле, сильнее нуля – ведь если рассуждать в классическом сеттинге, с действительными числами, то событие с нулевой вероятностью – может произойти. Например, если вы бросаете безразмерную точку на действительную окружность, то вероятность попасть в любое конкретное действительное число тождественно равна нулю, но в какое-то число вы всегда попадёте. Другое дело, что точно записать такие попадания – не выйдет, потому что нельзя записать точно большинство действительных чисел.

Одно и то же пустое множество можно помещать в разные коробки, получая разные пустые коробки. А пустая коробка может служить существенным признаком. Посмотрим на CAA-записи в DNS. Интерпретация этих записей отличается в случае, когда запись есть, но её значение – пустая строка, и в случае, когда нет самой CAA-записи. Здесь буквально проявляется эффект, позволяющий строить натуральные числа из пустого множества: когда нет CAA-записи – это настоящий нуль, пустое множество; когда CAA-запись есть, но она пустая – это уже единица, потому что возможна только одна пустая CAA-запись (ну или так: все пустые CAA-записи – одинаковые). То есть, тут, с одной стороны, играет роль определение того, чего нет: “нет значения CAA-записи” против “нет самой CAA-записи”; с другой стороны – содержательный эффект возникает из погружения пустого множества в большую структуру. Это, в точности, процесс (∅=0, {∅}=1).

Процесс погружения ∅ в {} даёт основной инструмент для генерирования множеств. Фигурные скобки обозначают операцию “множество из (элементов)” (set of). Так, {∅} – это множество из одного элемента, пустого множества. При этом одноэлементное множество (singleton, синглетон) – это не то же самое, что один этот элемент. То есть, заметьте, что {} и {∅} (или, если хотите, {{}}) – сильно разные вещи. Если, борясь за логическую стройность, ввести дополнительно понятие “класса”, как способа избежать возникновения абсурдного “множества всех множеств”, то пересечение всех классов – это и будет пустое множество. Именно поэтому в английском, например, языке пустое множество правильно обозначать как the empty set, с определённым артиклем the, а не an empty set. “A set”, но “the empty set”.

Данное важное свойство закреплено, – обычно!, – и в современных языках программирования высокого уровня. Если написать, что var a := {1} (то есть, переменная a – это массив из одной целой единицы по определению), то станет верным, что 1 != a (то есть, одна целая единица не равна массиву, состоящему из одной целой единицы).

А если взять JavaScript, то можно наблюдать сразу несколько особенностей интерпретации пустого множества и “ссылок” на пустое множество в программировании:

const set = new Set();
const object = {};

set.add(1);
set.add("two");
set.add(object);
set.add(object);
set.add({});

console.log(set.size);
for (const item of set.keys()) { 
  console.log(item);
}

– эта программа напечатает вот что:

4
1
two
Object {  }
Object {  }

– ничего странного, но довольно показательно.

Оставим JavaScript и его объекты. В шумерских способах записи чисел для обозначения отсутствия единиц использовали пробел. Занятно, что в шумерской системе, изначально, отличались обозначения для единиц, относящихся к разным типам объектов: предположим, обозначения для мер зерновых отличались от обозначений для мер воды. Это, конечно, связано с тем, что древнейшие системы просто фиксировали количество объектов при помощи изображений именно этих объектов, чтобы можно было попарно сопоставить изображение и реальность: видим три кувшина – рисуем три кувшина в качестве обозначения того, что кувшинов три; видим пять мехов с водой – рисуем пять мехов, в качестве обозначения, что мехов пять, и, возможно, знак воды рядом. Потому что тут ещё нет операции выноса типа выше числа: “кувшины” – три (палки); “меха” – пять (палок). И пустое множество демонстрирует свою уникальность: нет кувшинов, нет мехов – просто не обозначаем кувшины и меха. И именно поэтому пробел, как носитель “пустоты”, в шумерской схеме записи мог появиться только тогда, когда обозначения единиц для счёта уже отделились от типов объектов. То есть, введение пробела произошло сильно позже отказа от зарисовки “мехов и кувшинов”. Понятно, что отдельное обозначение для нуля требуется только в схеме “тип” – “количество”, где количество записывается абстрактно.

Пустое множество – аксиоматично. Так, чрезвычайно часто встречающийся в популярной литературе феномен, известный как “набор аксиом теории множеств” ZFC, буквально содержит аксиому о пустом множестве: “существует пустое множество”. Пустое тут – это то, в котором нет элементов, но оно – множество: то есть, множество, к которому не принадлежит ни один элемент. Получается, “пустота” множества может выступать как предикат: “[A] есть пустое”, и без пустого множества построение логических теорий становится затруднительным.

Удивительно, но побочный эффект того, что всякий элемент не принадлежит пустому множеству, вне зависисмости от типа, приводит к следующему обобщению: для элементов пустого множества всё что угодно – верно. Элементам пустого множества оказывается возможно приписать любое свойство. Это используется даже в модных “интернет-мемах”, как способ наведения сарказма:

никто: [%blah-blah-blah%]
иванов: подпрыгивает на батуте

– тут совсем условные обозначения, конечно: “[%blah-blah-blah%]” – пустое, “батут” – содержание. Главное – схема: “никто: {}, кто-то: {предмет мема}”. “Когда никто не догадался, кроме Иванова”.

Адрес записки: https://dxdt.ru/2026/02/23/17454/

Похожие записки:



Далее - мнения и дискуссии

(Сообщения ниже добавляются читателями сайта, через форму, расположенную в конце страницы.)

Написать комментарий

Ваш комментарий:

Введите ключевое слово "8ZZ49" латиницей СПРАВА НАЛЕВО (<--) без кавычек: (это необходимо для защиты от спама).

Если видите "капчу", то решите её. Это необходимо для отправки комментария ("капча" не применяется для зарегистрированных пользователей). Обычно, комментарии поступают на премодерацию, которая нередко занимает продолжительное время.