Ну, собственно, в Хаскелле контроль за побочными эффектами возложен именно на систему типов.
...
Ладно, господа давайте , подождем реакции Игоря-мне лично не очень понятно что он имел ввиду... на эту мысль наводят его определения....функций и процедур.
Может быть я разочарую публику, но честно должен признаться что не компетентен в Хаскеле. Так что здесь пока без комментариев.
Как я понял речь идет именно о разделении чистый -грязный (об устранении побочного эффекта речь не идет). Но зачем Ф и П -может хватит модификатора PURE в заголовке? Это по внешнему виду. Возникает вопрос как обеспечить это ?
Введение модификатора сулит, казалось бы, дополнительную гибкость: хочешь - объявляй чистую функцию, а хочешь - грязную. Но здесь не всё так просто. По большому счёту нужно чтобы не только функции были чистыми, но и выражения. У выражения и у функции схожая цель: вычислить значение. Хотя средства, ну и нотация, могут быть разные.
Представьте себе. Сегодня вот эта функция была у нас чистая, а завтра мы решили её сделать грязной (убрали модификатор PURE и добавили в неё вывод в лог). Но при этом все выражения в которых она была использована в качестве операнда, мгновенно стали грязными. Теперь нам надо отыскать все 120 этих выражений, разбросанных по 30 модулям, и в каждом из этих случаев решить критично это изменение или нет.
Простейший гемор - вы определяете набор совершенно чистых функций = которые прекрасно компилируются = но делаете из них DLL - и компилятор перестает считать их таковыми (Хотя они ими ОСТАЛИСЬ) Wink
А вот тут стоп! Использование DLL - это платформозависимый вопрос. Правила платформы легко могут вступить в противоречие с правилами языка, который мы используем. И вообще, все внешние сущности (например, из DLL) не обязаны подчиняться правилам нашего языка. Уповать на то, что вот эта DLL была написана на нашем языке, в общем случае не приходится.
Данные в немаленьких системах не лежат настолько открыто, чтобы функции могли "прочитать" все что нужно. Данные инкапсулированы и скрыты за абстракциями. Т.е., разделение на процедуры/функции должно распространятся и на методы (связанные процедуры/функции).
Мне кажется более правильным подход к инкапсуляции, принятый в Оберонах, нежели в классическом ООП. В Оберонах любые поля и методы любого объекта, объявленного в каком-либо модуле, доступны из любой точки этого модуля. Так что, исходный посыл, что "данные инкапсулированы и скрыты за абстракциями" получается как бы не верен.
Насчёт того, что методы также должны разделяться на процедуры/функции, согласен с Вами.
Кстати, здесь встаёт интересный вопрос, а разрешить ли методам-функциям (чистым) изменение полей своего объекта? Здесь Вы меня застали врасплох
Надо бы здесь хорошенько подумать, можно сообща.
Вы не можете заранее (в абстрактном интерфейсе) определить будет ли метод функцией (const), потому что вы ничего не можете предполагать о реализации этого метода.
Да, в С++ не могу ничего утверждать. Ну, а в нашем абстрактном (пока) языке могу. Если метод в абстрактном интерфейсе был объявлен как
function, то и все его реализации должны быть функциями. То есть не допускается полиморфизм такого рода, что функция в наследниках превращается в процедуру, и наоборот.
Что касается того, что чистые функции очень маленькие (игрушечные) и потому почти бесполезны, то это не справедливо по отношению к функциям. Функции могут быть исключительно сложны. Например, функция может вычислять оптимальный коэффициент по Калману для стохастической ситемы N-того порядка. Такую функцию ещё и разбивать придётся на вложенные функции. Несколько страниц точно займёт.