Когда мы привыкли к ленивому языку, нам не избежать чистого. Обратное неверно, но примечательно, что на практике большинство чистых языков программирования также ленивы. Почему? Поскольку в языке вызова по значению, независимо от того, работает он или нет, соблазн разрешить неограниченные побочные эффекты внутри «функции» почти непреодолим.
Чистота - это большая ставка с далеко идущими последствиями. Неограниченные побочные эффекты, несомненно, очень удобны. Из-за отсутствия побочных эффектов ввод-вывод в Haskell изначально был до боли неуклюжим, что сильно смущало. Необходимость, будучи матерью изобретения, в конечном итоге привела к изобретению монадического ввода-вывода, который мы теперь рассматриваем как один из главных вкладов Haskell в мир, как мы обсудим более подробно в разделе 7.
Вопрос о том, является ли чистый язык (с монадическими эффектами) в конечном итоге лучшим способом написания программ, все еще остается открытым, но это определенно радикальная и элегантная атака на проблему программирования, и именно эта комбинация силы и красоты мотивировала разработчиков. дизайнеров. Оглядываясь назад, можно сказать, что, пожалуй, самое большое преимущество лени - это не лень как таковая, а то, что она сохраняет нас чистыми и тем самым мотивирует большую продуктивную работу над монадами и инкапсулированным состоянием.
Теперь я думаю, что в лени важно то, что она сохраняла нашу чистоту. [...]
[...] если у вас есть ленивый вычислитель, труднее точно предсказать, когда выражение будет вычислено. Это означает, что если вы хотите что-то напечатать на экране, каждый язык с вызовом по значению, в котором порядок оценки полностью ясен, делает это, имея нечистую «функцию» - я заключил ее в кавычки, потому что теперь она это вообще не функция - с типом что-то вроде строки для единицы. Вы вызываете эту функцию, и в качестве побочного эффекта она помещает что-то на экран. Вот что происходит в Лиспе; это также происходит в ML. Это происходит практически во всех языках с вызовом по значению.
Теперь на чистом языке, если у вас есть функция от строки к единице, вам никогда не придется ее вызывать, потому что вы знаете, что она просто дает единицу ответа. Это все, что может сделать функция, это дать вам ответ. И вы знаете ответ. Но, конечно, если у него есть побочные эффекты, очень важно, чтобы вы его назвали. На ленивом языке проблема в том, что если вы скажете «f
применено к print "hello"
», то для вызывающей функции не будет очевидно, оценивает ли f
свой первый аргумент. Это как-то связано с внутренностями функции. И если вы передадите ему два аргумента, f
из print "hello"
и print "goodbye"
, тогда вы можете напечатать один или оба в любом порядке или ни в одном из них. Так или иначе, с ленивой оценкой выполнение ввода / вывода с помощью побочного эффекта просто невозможно. Так нельзя писать разумные, надежные и предсказуемые программы. Так что нам пришлось с этим смириться. На самом деле это было немного неловко, потому что вы не могли делать никаких вводов / выводов, о которых можно было бы говорить. Так что долгое время у нас были программы, которые могли просто преобразовывать строку в строку. Это то, что делала вся программа. Входная строка была входом, а строка результата была выходом, и это все, что программа действительно могла когда-либо делать.
Вы могли бы немного поумничать, заставив строку вывода кодировать некоторые команды вывода, которые интерпретировались каким-то внешним интерпретатором. Таким образом, в выходной строке может быть сказано: «Распечатайте это на экране; записать это на диск ». Переводчик действительно мог это сделать. Итак, вы представляете, что функциональная программа очень хороша и чиста, и есть что-то вроде этого злобного интерпретатора, который интерпретирует строку команд. Но тогда, конечно, если вы читаете файл, как вы вернете ввод в программу? Что ж, это не проблема, потому что вы можете вывести строку команд, которые интерпретируются злобным интерпретатором, и, используя ленивую оценку, он может выгружать результаты обратно во входные данные программы. Итак, программа теперь принимает поток ответов на поток запросов. Поток запросов идет к злобному интерпретатору, который творит дела с миром. Каждый запрос генерирует ответ, который затем возвращается на вход. А поскольку вычисление является ленивым, программа выдала ответ как раз вовремя, чтобы завершить цикл и использовать его в качестве входных данных. Но это было немного хрупко, потому что, если вы слишком жадно израсходовали свой ответ, вы попали в своего рода тупик. Потому что вы будете просить ответ на вопрос, который еще не выплюнул из своего бэкенда.
Дело в том, что лень загнала нас в угол, в котором мы должны были думать о способах решения этой проблемы ввода-вывода. Я думаю, что это было чрезвычайно важно. Самое главное в лени - это то, что она нас туда привела.
getFirstTrue p = head . filter p
, не беспокоясь о том, что он пройдет по всему списку перед возвратом первого элемента. Если вы используете строгую оценку, вы хотите избежать этого. Это становится более важным при смешивании таких вещей, как складки / карты и т. Д. - person Bakuriu   schedule 17.07.2015