iamjaph ([personal profile] iamjaph) wrote2010-12-03 08:06 am
Entry tags:

О чистоте и лени

После N-ной провальной попытки изучить Haskell и понять суть религии под названием "монадический фетишизм", решил изобрести свой "велосипед", то есть чистый и ленивый язык программирования.

Для любой открытой системы важным моментов является взаимодействие с внешним миром. В данном случаем - порядок обмена информацией.

У энергичных языков порядок определяется непосредственно самой последовательностью инструкций в программе. Напротив, для ленивых языков последовательность выполнения инструкций неопределена, а значения вычисляются по мере необходимости. Поэтому для осуществления взаимодействия с внешним миром в ленивые языки порядок вводиться искусственно.

Одним из способов упорядочивания вычислений является ввод дополнительных переменных-маркеров, при помощи которых указываются дополнительные зависимости между подпрограммами. Например, подпрограмма "C" зависит от переменной "b", которая определяется в подпрограмме "B", в свою очередь подпрограмма "B" зависит от переменной "a", значение которой определяется в подпрограмме "A", что приводит к выполнению сначала подпрограммы "A", затем "B" и лишь затем "C". Эти переменные маркеры в Mozart-OZ получили название свободные (unbound) переменные, а в Clean - уникальные типы.

Другим способом упорядочивание вычислений является использование стиля передачи продолжений. Однако этот стиль труден для использования им требует модификации подпрограмм. К счастью последнего можно избежать при помощи подпрограммы-обертки. В Haskell этой оберткой является оператор bind, а монады по сути не что иное, как своеобразный "концептуальный сахар" над стилем передачи продолжений. В свою очередь Haskell оператор do является "синтаксическим сахаром" вокруг монад, создающих иллюзию того, что переменные меняют свое значение.

Так что на самом деле Haskell, как и Clean, - абсолютно чистый язык, а религия "монадический фетишизм" - удел тех, кто на видеть разницы между иллюзией и реальностью.

P.S.
Во загнул! С другой стороны, что взять с простого физ-химика, волей случая написавшего несколько маленьких программ на Perl.

[identity profile] thesz.livejournal.com 2010-12-03 09:02 am (UTC)(link)
>монады по сути не что иное, как своеобразный "концептуальный сахар" над стилем передачи продолжений.

Эту штука пошире будет.

Есть Monad Maybe, Monad [], Monad (Either l), Monad (State s) и тп.

[identity profile] nponeccop.livejournal.com 2010-12-04 01:59 pm (UTC)(link)
> У энергичных языков порядок определяется непосредственно
> самой последовательностью инструкций в программе. Напротив,
> для ленивых языков последовательность выполнения инструкций
> неопределена, а значения вычисляются по мере необходимости.

Термины в математике - абстрактные последовательности слов, в общем случае не поддающиеся лингвистической декомпозиции. Термин "call by need" нельзя интерпретировать так, как будто это словосочетание английского языка. Попытаясь понять этот абстрактный смысл нематематически, как будто смыслы составляющих термин слов "вызов" и "необходимость" являются частью составного смысла, как будто есть какие-то вызовы и какая-то необходимость, вы зашли в тупик.

Не используйте метафор, используйте только математический смысл, который заключается в том, что call by need в лямбда-исчислении - это то же самое, что нормальный порядок редукции. Нормальный порядок редукции определен чисто синтаксически, точно так же, как и аппликативный, и, соответственно, последовательность выполнения редукций и для ленивых, и для энергичных языков одинаково жёстко определена исходным текстом программы.

> Поэтому для осуществления взаимодействия с внешним миром в ленивые
> языки порядок вводиться искусственно.

Порядок в ленивых языках задан жёстко в определении нормального порядка редукции, и никакого искусственного порядка вводить не нужно.

Следующий абзац пропускаем, так как там много ошибок, которые я не представляю, как исправить - в свете вышеизложенного лучше полностью переписать этот абзац. Например, в контексте чисто функциональных хаскеля и клина употребляется слово "переменные", и типы названы переменными.

Продолжения - это особая управляющая конструкция, такая, как рекурсия, ветвление, цикл или безусловный переход. Преобразование в стиль с передачей продолжений - эквивалентное преобразование программы, после которого почти все управляющие конструкции заменятся на передачу продолжения. К упорядочиванию вычислений имеет такое же отношение, как цикл. Но вы же не говорите, что цикл в Си служит для создания порядка в изначально неопределенной последовательности вычислений.

Далее вы снова ушли в переменные меняющие значения. Перепишите без этого, так я не могу понять вашу мысль

Теперь по сути

[identity profile] nponeccop.livejournal.com 2010-12-04 02:44 pm (UTC)(link)
Для начала, надо сформулировать вопрос, на которые вы хотите найти ответ. Вопросы могут быть такие:

1) Что такое монады?

Ответ на этот вопрос вам не нужен. Это особые моноиды (полугруппы, кажется, по-русски), определенные для особых категорий в теории категорий. Ответ столь же бесполезен, как и знание того, что такое строгие функции (строгие функции - это не "функции, которые всегда используют свой аргумент", а функции, сохраняющие нижний элемент в особых частично упорядоченных множествах в теории доменов).

2) Что такое монады в Хаскеле?

Это особая абстрактная управляющая структура.

3) В чем польза хаскелевцам от наличия такого странного модуля, как Control.Monad?

Повторное использование кода. Функции из этого модуля вроде mapM и liftM2 удается повторно использовать в чрезвычайно большом количестве предметных областей. Монадический фетишизм заключается в том, что людей возбуждает, если функцию mapM удаётся применить в каком-то неожиданном месте. Т.е. пишешь-себе пишешь, а потом бах - обнаруживаешь: "Ба, да это я половину контрол-монад заимплементил, надо срочно выбросить 100 зря написанных строк и написать import Control.Monad". Собственно возбуждение наступает лишь в клинических случаях - люди учили монады чтобы делать ио, а потом прозрели, что оказывается в Хаскеле есть абстракции управления. В менее запущенных случаях человека возбуждают не только монады, а вообще все абстракции управления (стрелки, обобщенные свертки, функторы и аппликативные функторы, вся typeclassopedia). Но такие люди выглядят не фанатами, а занудами, т.к. они не могут похвастаться знанием фраз типа "категория эндофункторов", а "абстракции управления" - это недостаточно заумно, т.к. и "абстракция", и "управление" есть даже в книгах по джаве. С другой стороны, люди, бросающиеся на каждом углу словами "катаморфизм", не производят впечатления фетишистов, так как рядовому кодеру непонятно, зачем это нужно, когда можно писать рекурсивную лапшу. В случае монад же вопрос "зачем нужен ввод-вывод" покажется нелепым даже императивному программисту, так что их как-то приходится постигать всем.

4) Зачем ввод-вывод в Хаскеле организован таким странным образом?

Это уже не монадический фетишизм, а пуристический. Об этом в следующем комментарии

Пуристический фетишизм

[identity profile] nponeccop.livejournal.com 2010-12-04 03:17 pm (UTC)(link)
Если очень кратко - то ввод-вывод в Хаскеле так сделан для радикального упрощения как написания, так и компиляции программ.

В обычных языках и компилятор при оптимизациях, и программист при рефакторингах должны помнить, занимается ли функция вводом-выводом или нет. Скажем, в Си

int x = foo(3);
x = 5;

можно заменить на int x = 5 только в случае, если foo не занимается вводом-выводом. Соответственно, в компиляторе проверки на потенциальное(!) наличие ввода-вывода должны быть расставлены повсеместно. Даже присваивания не доставляют столько хлопот компилятору, как ввод-вывод. Соответственно, если удастся сделать язык без ввода-вывода - то это существенно упростит всё: компиляторы, инструменты рефакторинга и анализа, работу программистов и т п.

Поэтому авторы Хаскеля (конкретно, Вадлер) придумали, как сделать хаскель без ввода-вывода вообще (ввода-вывода в Хаскеле нет, если вы не знали). И случайно оказалось, что проклятый mapM и сюда пролез.

В-общем, осталось ответить на вопросы:

1) Почему ввод-вывод доставляет столько проблем оптимизатору, что от него стоит избавиться?
2) Если в Хаскеле ввода-вывода нет, то как на Хаскеле читают файлы? (на Хаскеле файлы, строго говоря, и не читают)

[identity profile] beroal.livejournal.com 2011-01-06 02:29 pm (UTC)(link)
Плохо то, что слово «вычисление» уже начало означать «изменение памяти компьютера». Вычисляли же люди и до компьютеров, и перечёркивали написанное на бумаге только если оно было написано не правильно. :) Поэтому я бы говорил не о «порядке вычислений», а о порядке обмена информацией или о порядке запуска подпрограмм. Порядок вычислений, конечно же, тоже существует, и именно он не нужен. В каком порядке не вычисляй, результат будет одинаковый.

[identity profile] udpn.livejournal.com 2011-03-03 11:12 am (UTC)(link)
Опа, еще один химико-программист!
Присоединяйтесь к нам ;)

aamonster, sharpc, udpn