Функциональное программирование использует постоянные структуры данных и неизменные объекты. Мой вопрос: почему важно иметь такие структуры данных здесь? Я хочу понять на низком уровне, что произойдет, если структура данных не является постоянной? Будет ли программа зависать чаще?
22
Ответы:
Когда вы работаете с неизменяемыми объектами данных, функции обладают свойством, что каждый раз, когда вы вызываете их с одинаковыми входными данными, они выдают одинаковые выходные данные. Это облегчает концептуализацию вычислений и делает их правильными. Это также облегчает их тестирование.
Это только начало. Поскольку математика долгое время работала с функциями, существует множество методов рассуждения, которые мы можем позаимствовать у математики и использовать их для строгого рассуждения о программах. Самым важным преимуществом с моей точки зрения является то, что системы типов для функциональных программ хорошо разработаны. Таким образом, если вы допустите ошибку где-то, очень высоки шансы, что она будет отображаться как несоответствие типов. Таким образом, типизированные функциональные программы имеют тенденцию быть намного более надежными, чем императивные программы.
Напротив, когда вы работаете с изменяемыми объектами данных, у вас сначала возникает когнитивная нагрузка: запоминать и управлять несколькими состояниями, через которые проходит объект во время вычислений. Вы должны позаботиться о том, чтобы сделать все в правильном порядке, убедившись, что все свойства, необходимые для определенного шага, удовлетворены на этом этапе. Легко совершать ошибки, а системы типов не достаточно мощны, чтобы уловить эти ошибки.
Математика никогда не работала с изменчивыми объектами данных. Таким образом, мы не можем позаимствовать у них методы рассуждения. Есть много наших собственных методов, разработанных в области компьютерных наук, особенно Floyd-Hoare Logic . Однако освоить их сложнее, чем стандартные математические приемы, большинство студентов не могут с ними справиться и поэтому их редко обучают.
Для быстрого обзора того, как эти две парадигмы различаются, вы можете проконсультироваться с несколькими первыми раздаточными материалами моих лекционных заметок о принципах языков программирования .
источник
Это проще для корректной работы со структурами данных стойких , чем для работы с изменяемыми структурами данных. Это, я бы сказал, главное преимущество.
Конечно, теоретически, все, что мы делаем с постоянными структурами данных, мы можем делать и с изменяемыми, и наоборот. Во многих случаях постоянные структуры данных влекут за собой дополнительные расходы, обычно потому, что их части необходимо копировать. Эти соображения сделали бы постоянные структуры данных гораздо менее привлекательными 30 лет назад, когда у суперкомпьютеров было меньше памяти, чем у вашего мобильного телефона. Но в настоящее время основными узкими местами в производстве программного обеспечения являются время разработки и затраты на обслуживание. Таким образом, мы готовы пожертвовать некоторой эффективностью в исполнении для эффективности в развитии.
Почему проще использовать постоянные структуры данных? Потому что люди действительно плохо отслеживают псевдонимы и другие неожиданные взаимодействия между различными частями программы. Они автоматически думают, что, потому что две вещи называются
x
иy
, то не имеют ничего общего. Прежде всего, нужно понять, что «утренняя звезда» и «вечерняя звезда» - это одно и то же. Точно так же очень легко забыть о том, что структура данных может измениться, потому что с ней работают другие потоки, или потому что мы вызвали метод, который может изменить структуру данных и т. Д. Многие из этих проблем просто отсутствуют, когда мы работаем с постоянные структуры данных.Постоянные структуры данных также имеют другие технические преимущества. Как правило, их легче оптимизировать. Например, вы всегда можете свободно скопировать постоянную структуру данных на другой узел в вашем облаке, если вы не хотите беспокоиться о синхронизации.
источник
В дополнение к ответам других и укреплению математического подхода, функциональное программирование также имеет хорошую синергию с реляционной алгеброй и связями Галуа.
Это чрезвычайно полезно в области формальных методов.
Например:
пример
Тройка Хоара может быть выражена как контракт , где{p}P{q} [P]⋅ϕp⊆ϕq⋅[P]
Этот подход также позволяет рассчитывать самые слабые предварительные условия и самые сильные после условия , что полезно в ряде ситуаций.
источник
Давайте рассмотрим генератор псевдослучайных чисел с огромным пространством состояний (например, « твистер Мерсенна » с состоянием 2450 байт) в качестве структуры данных. На самом деле мы не хотим использовать какое-либо случайное число более одного раза, поэтому, похоже, нет особых оснований для реализации этого в качестве неизменяемой постоянной структуры данных. Теперь давайте спросим себя, что может пойти не так в следующем коде:
Большинство языков программирования не указывают порядок, в котором
MonteCarloIntegral_Bulk
иMonteCarloIntegral_Boundary
будут оцениваться. Если оба принимают в качестве аргумента ссылку на изменяемый mt_gen, результат этого вычисления может зависеть от платформы. Что еще хуже, могут быть платформы, на которых результат не воспроизводится между разными прогонами.Можно спроектировать эффективную изменяемую структуру данных для mt_gen так, чтобы любое чередование выполнения
MonteCarloIntegral_Bulk
иMonteCarloIntegral_Boundary
давало «правильный» результат, но другое чередование в целом приведет к другому «правильному» результату. Эта невоспроизводимость делает соответствующую функцию «нечистой», а также приводит к некоторым другим проблемам.Невоспроизводимости можно избежать, применяя фиксированный порядок последовательного выполнения. Но в этом случае код можно расположить так, чтобы в любой момент времени была доступна только одна ссылка на mt_gen. В типизированном функциональном языке программирования для обеспечения этого ограничения могут использоваться типы уникальности, что обеспечивает безопасные изменяемые обновления также в контексте чисто функциональных языков программирования. Все это может звучать красиво и модно, но по крайней мере в теории симуляции Монте-Карло смущающе параллельныи наше «решение» просто уничтожило это свойство. Это не просто теоретическая проблема, но очень реальная практическая проблема. Однако мы должны изменить (функциональность, предлагаемую) наш генератор псевдослучайных чисел и последовательность генерируемых им случайных чисел, и никакой язык программирования не может сделать это автоматически для нас. (Конечно, мы можем использовать другую библиотеку псевдослучайных чисел, которая уже предлагает необходимую функциональность.)
На низком уровне изменяемые структуры данных легко приводят к невоспроизводимости (и, следовательно, к нечистоте), если порядок выполнения не является последовательным и фиксированным. Типичная императивная стратегия для решения этих проблем состоит в том, чтобы иметь последовательные фазы с фиксированным порядком выполнения, во время которых изменяются структуры данных, и параллельные фазы с произвольным порядком выполнения, в течение которых все совместно изменяемые структуры данных остаются постоянными.
Андрей Бауэр поднял проблему псевдонимов для изменяемых структур данных. Интересно, что разные императивные языки, такие как Fortran и C, имеют разные предположения о допустимом псевдониме аргументов функций, и большинство программистов совершенно не знают, что их язык вообще имеет модель псевдонимов.
Неизменяемость и семантика значений могут быть немного переоценены. Более важно то, что система типов и логическая структура (например, модель абстрактной машины, модель псевдонимов, модель параллелизма или модель управления памятью) вашего языка программирования обеспечивают достаточную поддержку для «безопасной» работы с «эффективными» данными. структур. Введение «семантики перемещения» в C ++ 11 может показаться гигантским шагом назад с точки зрения чистоты и «безопасности» с теоретической точки зрения, но на практике все наоборот. Система типов и логическая структура языка были расширены для удаления огромных частей опасности, связанной с новой семантикой. (И даже если острые углы остаются, это не значит, что это не может быть улучшено «лучше»
Удай Редди поднял вопрос о том, что математика никогда не работала с изменяемыми объектами данных и что системы типов для функциональных программ хорошо разработаны для неизменных объектов данных. Это напомнило мне объяснение Жана-Ива Жирара о том, что математика не используется для работы со сменными объектами, когда он пытается мотивировать линейную логику.
Кто-то может спросить, как расширить систему типов и логическую структуру функциональных языков программирования, чтобы позволить «безопасно» работать с «эффективными» изменчивыми неперспективными структурами данных. Одной из проблем здесь может быть то, что классическая логика и булевы алгебры могут быть не самой лучшей логической структурой для работы с изменчивыми структурами данных. Возможно, линейная логика и коммутативные моноиды лучше подходят для этой задачи? Возможно, мне следует прочитать то, что сказал Филипп Вадлер о линейной логике как системе типов для функциональных языков программирования? Но даже если линейная логика не сможет решить эту проблему, это не означает, что система типов и логическая структура функционального языка программирования не могут быть расширены для обеспечения «безопасности» и «эффективности».
источник