Удар в темноте приведет вас к безумию. Существуют некоторые алгоритмы, которые, учитывая текущее понимание, вы не могли надеяться вывести внутренние работы между теперь и [предсказанным] концом юниверса, не зная точную информацию (потенциально включая закрытые ключи или внутреннее состояние). Конечно, некоторые из этих алгоритмов являются основой современной криптографии.
Если вы заранее знаете, что есть шаблон, который нужно открыть, иногда есть способы приблизиться к этому. Например, если набор данных содержит несколько входных значений, которые отличаются на 1, сравните соответствующие выходные значения:
7262627 -> 8172 7262628 -> 819 7262629 -> 1732 ... 7262631 -> 3558
Здесь достаточно ясно (учитывая несколько минут и калькулятор), что при увеличении входа на 1, выход увеличивается на 913 по модулю 8266 (т. Е. Простой линейный конгруэнтный генератор ).
Дифференциальный криптоанализ - относительно современная техника, используемая для анализа сила криптографических блочных шифров, полагаясь на аналогичную, но более сложную идею, где известен алгоритм шифрования, но предполагается, что закрытый ключ не является . Рассматриваются блоки ввода, отличающиеся друг от друга одним битом, и эффект этого бита прослеживается через шифр, чтобы определить, насколько вероятен каждый бит output для «переворачивания».
Другие способы приближения к этой проблеме состоят в том, чтобы посмотреть на крайности (максимальные, минимальные значения), распределение (приводящее к частотном анализе ), направление (числа всегда увеличиваются? ) и (если это разрешено) рассмотрим контекст, в котором были найдены наборы данных. Например, некоторые типы PIN-кодов всегда содержат повторенную цифру, чтобы облегчить их запоминание (я не говорю, что PIN-код может быть выведен из чего-либо другого - просто повторяющаяся цифра равна единице нет разряд беспокоиться!).
Я немного говорю об этом в Проектирование больших проектов на Haskell и в Проектирование и реализация XMonad. Инженерное дело в целом - это управление сложностью. Основными механизмами структурирования кода в Haskell для управления сложностью являются:
Система типов
Профилировщик
Чистота
Тестирование
Монады для структурирования
Классы типов и экзистенциальные типы
Параллелизм и параллелизм
par
в свою программу, чтобы превзойти конкурентов с помощью простого компонуемого параллелизма.Рефакторинг
Используйте FFI с умом
Мета-программирование
Упаковка и распространение
Предупреждения
-Wall
, чтобы сохранить ваш код чистый от запахов. Вы также можете посмотреть на Agda, Isabelle или Catch для большей уверенности. Для проверки, похожей на линт, см. Отличный hlint , который предложит улучшения. С помощью всех этих инструментов вы можете справиться со сложностью, удалив как можно больше взаимодействий между компонентами. В идеале у вас есть очень большая база чистого кода, которую действительно легко поддерживать, поскольку она композиционна. Это не всегда возможно, но к этому стоит стремиться.
В общем: разложите логические единицы вашей системы на наименьшие возможные ссылочно прозрачные компоненты,затем реализовать их в модулях. Глобальные или локальные среды для наборов компонентов (или внутри компонентов) могут быть отображены на монады. Используйте алгебраические типы данных для описания основных структур данных. Широко поделитесь этими определениями.
Проектирование больших программ на Haskell не сильно отличается от проектирования на других языках. Программирование в большом - это разбиение вашей проблемы на управляемые части, и то, как соединить их вместе; язык реализации менее важен.
Тем не менее, в большом проекте хорошо попытаться использовать систему типов, чтобы убедиться, что вы можете соединить ваши части только таким образом, чтобы это было правильно. Для этого можно использовать новые типы или фантомные типы, чтобы вещи, которые кажутся имеющими один и тот же тип, были разными.
Когда дело доходит до рефакторинга кода по ходу дела, чистота является большим благом, поэтому старайтесь сохранить как можно большую часть кода чистым. Чистый код легко рефакторить, потому что он не имеет скрытого взаимодействия с другими частями вашей программы.
Дон рассказал вам большинство деталей выше, но вот мои два цента, которые я получил, занимаясь на Haskell действительно серьезными программами с состоянием, такими как системные демоны.
В конце концов, вы живете в стеке монада-трансформер. В самом низу находится IO. Выше него каждый основной модуль (в абстрактном смысле, а не в смысле модуль в файле) отображает свое необходимое состояние на слой в этом стеке. Таким образом, если код подключения к базе данных спрятан в модуле, вы пишете его над типом MonadReader Connection m => ... -> m ... и тогда ваши функции базы данных всегда могут получить свое подключение без того, чтобы функции из других модулей знали о его существовании. В итоге вы можете получить один слой, несущий соединение с базой данных, другой - конфигурацию, третий - различные семафоры и mvars для разрешения параллелизма и синхронизации, третий - обработку лог-файлов и т.д.
Сначала разберитесь с обработкой ошибок и . Самым большим недостатком Haskell в больших системах на данный момент является обилие методов обработки ошибок, включая такие паршивые, как Maybe (что неправильно, потому что вы не можете вернуть никакой информации о том, что пошло не так; всегда используйте Either вместо Maybe, если только вы действительно не имеете в виду просто отсутствующие значения). Сначала определите, как вы собираетесь это делать, и установите адаптеры от различных механизмов обработки ошибок, используемых вашими библиотеками и другим кодом, к вашему окончательному механизму. Это спасет вас от многих неприятностей в дальнейшем.
Дополнение (извлечено из комментариев; спасибо Lii и liminalisht) -
больше обсуждений различных способов нарезки большой программы на монады в стеке:
Ben Kolera дает отличное практическое введение в эту тему, а Brian Hurt обсуждает решения проблемы lift
ing monadic actions in your custom monad. Джордж Уилсон показывает, как использовать mtl
для написания кода, который работает с любой монадой, реализующей необходимые типоклассы, а не с вашей пользовательской монадой. Карло Хамалайнен написал несколько коротких, полезных заметок, резюмирующих выступление Джорджа.