Определение по умолчанию
m >> k = m >>= \_ -> k
этого вроде как не гарантирует. Наверняка для IO в реализации хаскелля это так. Но я пока не вижу формальных гарантий именно такого поведения.
Тем, что это не присвоение, а определение функции. Присвоения в ленивых языках как такового нет, поскольку это чистой воды побочный эффект. И в этой строчке она не вызывается.
Конечно размыто. Но по-моему достаточно интуитивно понятно.
Конечно зыбкая. По-этому программисты и ищут точки опоры в виде парадигм, стилей, шаблонов проектирования и т.п.
Можно. В данном случае да, иной — это «ленивой», поскольку из ленивости вытекают многие из тех свойств, которые присущи функциональным языкам и воспринимаются как своеобразные маркеры «функциональности». Рассматривать в контексте ФП только ленивые языки, разумеется, является очень большим упрощением, поскольку ФП в современном понимании включает в себя далеко не только их. Но охватить всё я не в состоянии. Да и цель была другая. Я ставил целью показать, что суть функционального подхода не в том, что берется раз, два, три, десять свойств, которые должны соблюдаться в языке программирования, а берется некоторая теоретическая основа — система типизации, модель вычислений и прочее, на их основе создается язык, который исходя из этих основ обладает рядом «функциональных» свойств.
Ленивые вычисления имеют к ФП непосредственное отношение. Если вам известен императивный язык, целиком и полностью основанный на концепции ленивых вычислений — буду рад, если Вы расширите мой кругозор.
«чистота» — следствие как раз декларативности
Логическое программирование декларативно, но Пролог «чистоты» не предполагает. Ваше утверждение требует доказательства. Я, в свою очередь, продемонстрировал, что чистота — необходимое требование в случае, когда предполагается использование ленивых вычислений.
Вы будьте так любезны прекратить разговаривать через губу. Если Вам не понятно, я при изложении вполне сознательно упрощал и утрировал, чтобы не засорять внимание деталями, не имеющими прямого отношения к сути рассматриваемого вопроса. Наличие такого (возможного) примера что-то сущностно меняет? Или я должен был все возможные нюансы того, как происходит редукция изложить? Или следовало придерживаться большей математической строгости? Делаете замечание — потрудитесь написать по существу в чем автор ошибается и как это влияет на полученные выводы.
Вообще-то бремя доказательства обычно ложится на того, кто делает утверждение. Есть основания утверждать, что приведённый код может быть интерпретирован таким и только таким образом?
Конечно она скомбинирована внутрь main. У вас все используемые функции как-то скомбинированы — в этом смысл. Как это вам помогает понять где начнётся выполнение какой-то части конкретной функции в ленивых вычислениях?
В данном случае никаких значимых следствий мне не известно. Под «имитацией» ленивых вычислений я имел ввиду то, что в императивном по своей природе языке появляется синтаксическая конструкция, которая упрощает реализацию поведения, характерного для языков, явным образом использующих ленивую модель вычислений в качестве основного механизма функционирования. В статье я постоянно делаю на этом акцент: заимствование из одной парадигмы в другую — вещь совершенно нормальная. Разница только в том, является ли такой механизм естественным следствием какой-то фундаментальной концепции, либо же он спроектирован сознательно для реализации определенных возможностей языка.
Асинхронность предполагает, что мы примерно представляем порядок вычислений. В ленивой модели мы не знаем (гипотетически), когда часть кода, обернутая в IO, начнет выполняться — до или после момента, когда нам реально понадобится вычисленное значение. Из чего следует, что эти моменты должны быть разнесены по времени? Может, IO ведет себя подобно Async, но ведь это вроде как не обязательно.
Всё-таки это константа, хоть и имеющая значение, порождаемое функцией.
Все-таки нет, это функция, у которой нет аргументов.
Здесь неопытнй читатель наверняка подумает...
Если читатель сравнивает в категориях хуже/лучше, то заблудится в любом случае, безотносительно написанного. Надеюсь, что я достаточно ясно выразил мысль: есть вещи, которые естественны в рамках одной и другой модели вычислений, и у этих вещей есть способы практического применения. И полезные вещи всегда пытаются перенести из одной парадигмы в другую.
И здесь важно сказать явно — императивный и функциональный — это лишь стили
Вот нет. В первую очередь это точка зрения, с которой мы смотрим на алгоритмы и процесс вычислений, на процесс решения задачи. Нет никакого противостояния стилей. Есть алгоритмы, которые естественным образом появляются в рамках одной либо другой концепции. И поэтому полезно владеть обоими.
Я не пытался дать всеобъемлющее определение ФП. И вряд ли кто-то такое определение даст. Я напротив пытался объяснить, что оценивать «функциональность» программы по тому, соответствует ли она некому набору формальных признаков, занятие не слишком полезное. Что имеются причины, почему у одних программ эти свойства есть, а у других их может не быть, и они глубже, чем воля отдельного программиста или разработчиков языка. И на качество кода влияет понимание этих причин и их следствий, а не простое выполнение формальных критериев.
А программы на идрисе — императивные? А то он строгий по умолчанию.
Как я уже отвечал коллеге, это не более чем терминологический спор, непродуктивный до момента, пока Вы не предоставите удовлетворительное определение ФП. Я такое определение дал — это программирование в рамках ленивой модели вычислений. Это определение неидеально и, очевидно, неполно, и я даже на нем не пытаюсь настаивать. Из него выбивается часть языков, которые душа требует не класть в один ящик с типичными императивными. Но в то же время оно позволяет обосновать наличие свойств, инструментов и практик, характерных для функциональных программ. Если у вас есть другое, более конструктивное определение, из которого имеются интересные следствия (иначе зачем оно нужно?), то я с огромным удовольствием его приму.
А программы на функциональных языках, для теорий типов которых выполняется strong normalization theorem
Не могу же я все теории, используемые в ФП, даже из скромного подмножества известных мне охватить в одной статье. Наличие типизации очень многое меняет. Моей задачей было показать, что имеются более глубокие причины того, что функциональные программы имеют те свойства, которые имеют, чем дизайн языка. Конечно, ряд следствий можно получить из других предпосылок, а ряд свойств никак не следует из одной ленивости. Но простое воспроизведение «функциональных свойств» не делает язык «функциональным».
Для ответа на этот вопрос нам с Вами придется рассмотреть реализацию генераторов и оператора yield в питоне. И тогда получим сильно усложненный эквивалентный код, который все еще будет жадным.
Вариантов много. И установить, какая из возможностей в действительности имеет место можно только дав исчерпывающее определение ФП. Отсутствие которого и привело к проблеме. Такая вот рекурсия.
m >> k = m >>= \_ -> k
этого вроде как не гарантирует. Наверняка для IO в реализации хаскелля это так. Но я пока не вижу формальных гарантий именно такого поведения.
Конечно размыто. Но по-моему достаточно интуитивно понятно.
Конечно зыбкая. По-этому программисты и ищут точки опоры в виде парадигм, стилей, шаблонов проектирования и т.п.
Это определенно не аксиома, значит оно должно следовать из каких-то предпосылок. Я спрашиваю: из каких?
readFile «1.txt» >> writeFile «2.txt» «blabla»
Какой закон для монады помешает сначала записать 2.txt, а после прочитать 1.txt? Без шуток, может я действительно что-то забыл или не знал.
Ленивые вычисления имеют к ФП непосредственное отношение. Если вам известен императивный язык, целиком и полностью основанный на концепции ленивых вычислений — буду рад, если Вы расширите мой кругозор.
Логическое программирование декларативно, но Пролог «чистоты» не предполагает. Ваше утверждение требует доказательства. Я, в свою очередь, продемонстрировал, что чистота — необходимое требование в случае, когда предполагается использование ленивых вычислений.
С чего Вы решили?
Все-таки нет, это функция, у которой нет аргументов.
Если читатель сравнивает в категориях хуже/лучше, то заблудится в любом случае, безотносительно написанного. Надеюсь, что я достаточно ясно выразил мысль: есть вещи, которые естественны в рамках одной и другой модели вычислений, и у этих вещей есть способы практического применения. И полезные вещи всегда пытаются перенести из одной парадигмы в другую.
Вот нет. В первую очередь это точка зрения, с которой мы смотрим на алгоритмы и процесс вычислений, на процесс решения задачи. Нет никакого противостояния стилей. Есть алгоритмы, которые естественным образом появляются в рамках одной либо другой концепции. И поэтому полезно владеть обоими.
Я не пытался дать всеобъемлющее определение ФП. И вряд ли кто-то такое определение даст. Я напротив пытался объяснить, что оценивать «функциональность» программы по тому, соответствует ли она некому набору формальных признаков, занятие не слишком полезное. Что имеются причины, почему у одних программ эти свойства есть, а у других их может не быть, и они глубже, чем воля отдельного программиста или разработчиков языка. И на качество кода влияет понимание этих причин и их следствий, а не простое выполнение формальных критериев.
Как я уже отвечал коллеге, это не более чем терминологический спор, непродуктивный до момента, пока Вы не предоставите удовлетворительное определение ФП. Я такое определение дал — это программирование в рамках ленивой модели вычислений. Это определение неидеально и, очевидно, неполно, и я даже на нем не пытаюсь настаивать. Из него выбивается часть языков, которые душа требует не класть в один ящик с типичными императивными. Но в то же время оно позволяет обосновать наличие свойств, инструментов и практик, характерных для функциональных программ. Если у вас есть другое, более конструктивное определение, из которого имеются интересные следствия (иначе зачем оно нужно?), то я с огромным удовольствием его приму.
Не могу же я все теории, используемые в ФП, даже из скромного подмножества известных мне охватить в одной статье. Наличие типизации очень многое меняет. Моей задачей было показать, что имеются более глубокие причины того, что функциональные программы имеют те свойства, которые имеют, чем дизайн языка. Конечно, ряд следствий можно получить из других предпосылок, а ряд свойств никак не следует из одной ленивости. Но простое воспроизведение «функциональных свойств» не делает язык «функциональным».