Я хочу понять на низком уровне, что произойдет, если структура данных не является постоянной?
Давайте рассмотрим генератор псевдослучайных чисел с огромным пространством состояний (например, « твистер Мерсенна » с состоянием 2450 байт) в качестве структуры данных. На самом деле мы не хотим использовать какое-либо случайное число более одного раза, поэтому, похоже, нет особых оснований для реализации этого в качестве неизменяемой постоянной структуры данных. Теперь давайте спросим себя, что может пойти не так в следующем коде:
mt_gen = CreateMersenneTwisterPRNGen(seed)
integral = MonteCarloIntegral_Bulk(mt_gen) + MonteCarloIntegral_Boundary(mt_gen)
Большинство языков программирования не указывают порядок, в котором MonteCarloIntegral_Bulk
и MonteCarloIntegral_Boundary
будут оцениваться. Если оба принимают в качестве аргумента ссылку на изменяемый mt_gen, результат этого вычисления может зависеть от платформы. Что еще хуже, могут быть платформы, на которых результат не воспроизводится между разными прогонами.
Можно спроектировать эффективную изменяемую структуру данных для mt_gen так, чтобы любое чередование выполнения MonteCarloIntegral_Bulk
и MonteCarloIntegral_Boundary
давало «правильный» результат, но другое чередование в целом приведет к другому «правильному» результату. Эта невоспроизводимость делает соответствующую функцию «нечистой», а также приводит к некоторым другим проблемам.
Невоспроизводимости можно избежать, применяя фиксированный порядок последовательного выполнения. Но в этом случае код можно расположить так, чтобы в любой момент времени была доступна только одна ссылка на mt_gen. В типизированном функциональном языке программирования для обеспечения этого ограничения могут использоваться типы уникальности, что обеспечивает безопасные изменяемые обновления также в контексте чисто функциональных языков программирования. Все это может звучать красиво и модно, но по крайней мере в теории симуляции Монте-Карло смущающе параллельныи наше «решение» просто уничтожило это свойство. Это не просто теоретическая проблема, но очень реальная практическая проблема. Однако мы должны изменить (функциональность, предлагаемую) наш генератор псевдослучайных чисел и последовательность генерируемых им случайных чисел, и никакой язык программирования не может сделать это автоматически для нас. (Конечно, мы можем использовать другую библиотеку псевдослучайных чисел, которая уже предлагает необходимую функциональность.)
На низком уровне изменяемые структуры данных легко приводят к невоспроизводимости (и, следовательно, к нечистоте), если порядок выполнения не является последовательным и фиксированным. Типичная императивная стратегия для решения этих проблем состоит в том, чтобы иметь последовательные фазы с фиксированным порядком выполнения, во время которых изменяются структуры данных, и параллельные фазы с произвольным порядком выполнения, в течение которых все совместно изменяемые структуры данных остаются постоянными.
Андрей Бауэр поднял проблему псевдонимов для изменяемых структур данных. Интересно, что разные императивные языки, такие как Fortran и C, имеют разные предположения о допустимом псевдониме аргументов функций, и большинство программистов совершенно не знают, что их язык вообще имеет модель псевдонимов.
Неизменяемость и семантика значений могут быть немного переоценены. Более важно то, что система типов и логическая структура (например, модель абстрактной машины, модель псевдонимов, модель параллелизма или модель управления памятью) вашего языка программирования обеспечивают достаточную поддержку для «безопасной» работы с «эффективными» данными. структур. Введение «семантики перемещения» в C ++ 11 может показаться гигантским шагом назад с точки зрения чистоты и «безопасности» с теоретической точки зрения, но на практике все наоборот. Система типов и логическая структура языка были расширены для удаления огромных частей опасности, связанной с новой семантикой. (И даже если острые углы остаются, это не значит, что это не может быть улучшено «лучше»
Удай Редди поднял вопрос о том, что математика никогда не работала с изменяемыми объектами данных и что системы типов для функциональных программ хорошо разработаны для неизменных объектов данных. Это напомнило мне объяснение Жана-Ива Жирара о том, что математика не используется для работы со сменными объектами, когда он пытается мотивировать линейную логику.
Кто-то может спросить, как расширить систему типов и логическую структуру функциональных языков программирования, чтобы позволить «безопасно» работать с «эффективными» изменчивыми неперспективными структурами данных. Одной из проблем здесь может быть то, что классическая логика и булевы алгебры могут быть не самой лучшей логической структурой для работы с изменчивыми структурами данных. Возможно, линейная логика и коммутативные моноиды лучше подходят для этой задачи? Возможно, мне следует прочитать то, что сказал Филипп Вадлер о линейной логике как системе типов для функциональных языков программирования? Но даже если линейная логика не сможет решить эту проблему, это не означает, что система типов и логическая структура функционального языка программирования не могут быть расширены для обеспечения «безопасности» и «эффективности».