Предисловие
Last updated
Last updated
Уже некоторое время я обдумываю идею написать книгу о теории категорий, предназначенную для программистов. Обратите внимание: не для специалистов в области информатики, а именно для программистов, которые в большинстве своем инженеры, а не ученые. Знаю, звучит безумно, и я вполне это осознаю. Не буду отрицать, что между наукой и инженерией огромная пропасть, - я работал по обе стороны баррикад. Однако я всегда ощущал сильную тягу к объяснению чего бы то ни было. Я восхищен талантом Ричарда Фейнмана к простым объяснениям. Да, я не Фейнман, но сделаю все, что в моих силах. Начну с публикации этого предисловия с целью мотивировать читателя изучить теорию категорий и в надежде начать обсуждение и получить отзывы.
Я попытаюсь в нескольких абзацах убедить читателя, что эта книга написана именно для него, и любые имеющиеся причины не изучать одну из самых абстрактных областей математики в свое "обширное свободное время" совершенно необоснованны.
Мой оптимизм основан на нескольких наблюдениях. Во-первых, теория категорий - это кладезь невероятно полезных в программировании идей. Создатели языка Haskell черпали оттуда вдохновение долгое время, и плоды их трудов медленно просачиваются в другие языки, но этот процесс проистекает крайне медленно. Необходимо его ускорить.
Во-вторых, математика многогранна, и разные области математики привлекают внимание разных аудиторий. Вы можете на дух не переносить математический анализ или алгебру, но это не означает, что Вам не понравится теория категорий. Возьму на себя смелость утверждать, что теория категорий очень хорошо соответствует образу мышления программиста. Все потому, что теория категорий рассматривает структуру, а не детали. Ту самую структуру, которая делает программы компонуемыми.
Композиция является основополагающим понятием теории категорий - это часть определения категории как таковой. И я уверен, что композиция - существо программирования. Мы всегда собирали наши большие игрушки из отдельных деталек, задолго до того, как одного великого инженера посетила идея процедур. В прошлом принципы структурного программирования произвели революцию, потому что позволили компоновать независимые части исходного кода. Затем появилось объектно-ориентированное программирование, в основе которого лежит композиция объектов. Функциональное программирование, помимо компоновки функций и алгебраических структур данных, позволяет применять композицию к конкурентному программированию, что практически невозможно в других парадигмах программирования.
И наконец, у меня есть секретное оружие - тесак, которым я буду безжалостно разделывать тушку математики, чтобы сделать ее более аппетитной для программистов. Профессиональные математики вынуждены излагать свои предположения предельно точно, тщательно проверять все высказывания и строго выстраивать доказательства. Поэтому математические научные статьи и книги чрезвычайно сложны для понимания не-математиками. Я физик по образованию, а физики добились впечатляющих успехов, рассуждая неформально. Математики смеялись над дельта-функцией Дирака, которая была выведена "на глаз" выдающимся физиком Полем Дираком для решения некоторых дифференциальных уравнений. Смех прекратился, когда была открыта целая область математического анализа - теория распределений - которая формализовала идеи Дирака.
Конечно, при использовании умозрительных аргументов есть риск сказать что-то вопиюще неверное, поэтому я постараюсь, чтобы за неформальными утверждениями в этой книге стояла серьезная математическая теория. Да-да, на моей тумбочке около кровати лежит потрепанная книга Саундерса Маклейна "Теория категорий для работающего математика".
Так как эта книга для программистов, все основные принципы будут проиллюстрированы кодом. Вы, думаю, знаете, что функциональные языки ближе к математике, чем более популярные императивные. Они так же предоставляют больше возможностей для создания абстракций. Так что вполне оправдан соблазн сказать: "Вы должны изучить Haskell, и только потом богатства теории категорий станут вам доступны." Но это означало бы, что теория категорий неприменима за пределами функционального программирования, а это не так. Так что я приведу немало примеров на C++. Разумеется, синтаксис может оскорбить чувства эстетов, замысел может потеряться за фоне синтаксического шума, а время от времени придется просто копировать код вместо применения хороших абстракций. Хотя, впрочем, ничего нового для C++ программистов.
Однако Haskell никто не отменял. Не нужно становиться экспертом в этом языке, но он пригодится в качестве инструмента прототипирования и документирования идей, которые планируется реализовать на C++. Именно так я сам познакомился с Haskell. Оказалось, что его немногословный синтаксис и мощная система типов хорошо помогают в понимании и реализации шаблонов C++, а также структур данных и алгоритмов. Так как я не ожидаю от читателя знания Haskell, я не спеша познакомлю вас с этим языком программирования по ходу повествования.
Если Вы опытный программист, вы можете задаться вопросом: "Я программировал все это время, не беспокоясь о теории категорий или функциональных приемах, - так что же изменилось?" Нельзя не заметить, что императивные языки неуклонно пополняют свой репертуар функциональных возможностей. Даже Java, твердыня объектно-ориентированного программирования, впустила замыкания. C++ в наши дни развивается бешеными темпами - новый стандарт каждые три-четыре года - в попытке соответствовать меняющемуся миру. Все это - прелюдия к разрушительным изменениям или, как говорят физики, фазовому переходу. Если подогревать воду, со временем она начнет кипеть. Мы сейчас в положении лягушки, которой нужно решить - плавать дальше в постепенно закипающей воде либо начать искать альтернативы.
Описанные изменения происходят в том числе благодаря многоядерной революции. Доминирующая объектно-ориентированная парадигма программирования не дает никаких преимуществ при конкурентном и параллельном программировании. Наоборот - ООП поощряет опасные и полные багов архитектуры. Сокрытие данных, основная предпосылка ООП, в сочетании с общим к ним доступом и их мутациями - рецепт для условий гонки. Идея защищать данные мьютексами хороша, но, к сожалению, блокировки не компонуются, а их сокрытие делает появление взаимных блокировок более вероятным и сложным для отладки.
Но даже при отсутствии конкурентности растущая сложность программных комплексов испытывает императивную парадигму на прочность. Если просто - побочные эффекты выходят из под контроля. Понятно, что функции с побочными эффектами зачастую удобны и их легко писать. Эффекты в этих функциях, в принципе, могут быть указаны в их названии и в комментариях. Функции SetPassword
или WriteFile,
очевидно, изменяют некоторое состояние и создают побочные эффекты, и мы к этому привыкли. Только при композиции функций с побочными эффектами с другими, которые так же имеют побочные эффекты, возникают проблемы. Это все не означает, что побочные эффекты по сути своей - зло. Побочные эффекты бывает не просто заметить, и именно поэтому практически невозможно ими управлять в крупных проектах. Побочные эффекты не масштабируются, а императивное программирование целиком построено на побочных эффектах.
Изменения в аппаратном обеспечении и растущая сложность программ заставляют нас пересмотреть основы программирования. Как и строители огромных европейских готических соборов, мы столкнулись с непреодолимыми ограничениями наших материалов и знаний. В Бове, Франция, есть недостроенный готический собор Святого Петра, который олицетворяет человеческую борьбу с ограничениями. Его создатели планировали побить все рекорды высоты и легковесности, но столкнулись с чередой обрушений. Временные меры - железные балки и деревянные подпорки - предотвращают его разрушение, но, очевидно, что много чего пошло не так, как планировалось. В наши дни кажется чудом, что так много готических сооружений было построено без помощи современного материаловедения, компьютерного моделирования, метода конечных элементов, даже без общей физики и математики. Надеюсь, что будущие поколения будут так же восхищены нашими навыками программирования, которые мы демонстрируем при разработке сложных операционных систем, веб-серверов и инфраструктуры Интернета. И, честно говоря, они просто обязаны, так как мы создали все современное программное обеспечение на очень шатком теоретическом фундаменте. Нужно разобраться с фундаментом, если мы хотим двигаться дальше.
Балки, удерживающие собор Святого Петра от разрушения