«Ничего не оценивается, пока это не понадобится в другом месте» - это упрощенная метафора, которая не охватывает все аспекты ленивой оценки (например, не упоминает феномен строгости).
С теоретической точки зрения при разработке чистого языка (конечно, если он основан на каком-то лямбда-исчислении, а не на более экзотических моделях оценки) можно пойти тремя способами: строгий, нестрогий и тотальный.
У каждого из них есть свои достоинства и недостатки, поэтому вам необходимо ознакомиться с соответствующими исследовательскими работами.
Общие языки являются наиболее чистыми из трех. В двух других незавершение можно рассматривать как побочный эффект, поэтому для обеспечения эффективности реализации необходимо создать анализаторы строгости и целостности. Оба анализа неразрешимы, поэтому анализаторы никогда не могут быть полными.
Однако все языки наименее выразительны: полный язык не может быть полным по Тьюрингу. Частый подход к достижению достаточно хорошей выразительности - это иметь встроенную систему доказательств для хорошо обоснованной рекурсии, которую не намного проще построить, чем анализаторы для неполных языков.
С практической точки зрения нестрогая семантика позволяет вам более легко определять абстракции элементов управления, поскольку структуры управления по существу не являются строгими. В строгом языке вам все равно нужны места с нестрогой семантикой. Например. Конструкция if
имеет нестрогую семантику даже в строгих языках.
Так что, если ваш язык строгий, управляющие структуры - это особый случай. Напротив, нестрогий язык может быть одинаково нестрогим - для него нет неотъемлемой потребности в строгих конструкциях.
Что касается того, «кто это пишет десять раз до обеда» - это делает любой, кто использует Haskell в своих проектах. Я думаю, что разработка не игрушечного проекта с использованием языка (нестрогого языка в вашем случае) - лучший способ понять его преимущества и недостатки.
Ниже приведены несколько общих сценариев использования лени, проиллюстрированных неигровыми примерами:
Случаи, когда поток управления трудно предсказать. Подумайте о грамматиках атрибутов, когда вам без лени нужно выполнить топологическую сортировку атрибутов для разрешения зависимостей. Повторная сортировка кода каждый раз при изменении графа зависимостей нецелесообразна. В Haskell вы можете реализовать формализм грамматики атрибутов без явной сортировки, и на Hackage есть как минимум две фактические реализации. Грамматики атрибутов имеют широкое применение при построении компиляторов.
Подход «генерировать и искать» для решения многих задач оптимизации. На строгом языке вы должны чередовать генерацию и поиск, в Haskell вы просто составляете отдельные функции генерации и поиска, и ваш код остается синтаксически модульным, но чередуется во время выполнения. Подумайте о проблеме коммивояжера (TSP), когда вы генерируете все возможные туры, а затем просматриваете их, используя алгоритм ветвей и границ. Обратите внимание, что алгоритм перехода по границе проверяет только определенные первые города тура, генерируются только необходимые части маршрутов. Даже в самом чистом виде TSP имеет несколько применений, таких как планирование, логистика и производство микрочипов. Слегка измененный, он появляется как подзадача во многих областях, таких как секвенирование ДНК.
Ленивый код имеет немодульный поток управления, поэтому одна функция может иметь много возможных потоков управления в зависимости от среды, в которой она выполняется. Это явление можно рассматривать как своего рода «полиморфизм потока управления», поэтому абстракции ленивого потока управления являются более общими. чем их строгие аналоги, а стандартная библиотека функций высшего порядка гораздо полезнее на ленивом языке. Подумайте о генераторах, циклах и итераторах списков Python: функции списков в Haskell охватывают все три варианта использования, при этом поток управления адаптируется к различным сценариям использования из-за лени. Он не ограничивается списками - подумайте о Data.Arrow и итерациях, ленивых и строгих версиях монады состояния и т. Д. Также обратите внимание, что немодульный поток управления является одновременно преимуществом и недостатком, поскольку он усложняет рассуждения о производительности.
Ленивые, возможно, бесконечные структуры данных полезны не только в игрушечных примерах. См. Работы Конала Эллиотта о запоминании функций высшего порядка с помощью попыток. Бесконечные структуры данных выглядят как бесконечные пространства поиска (см. 2), бесконечные циклы и никогда не утомляющие генераторы в смысле Python (см. 3).
person
nponeccop
schedule
27.11.2011