Здравствуйте, AlexRK, Вы писали:
I>>Поддержка синтаксиса необязательна. хочешь хороший пример монады — посмотри Promise в джаваскрипте. I>>http://www.html5rocks.com/en/tutorials/es6/promises/
ARK>Посмотрел. Выглядит как ужасная грязь — даже на маленьких кусочках кода. ARK>Страшно подумать, что будет на больших.
Вот, можно упрятать грязь с помощью yield, это JS 6 — Harmony. Для запуска нужен например Node.js 0.11.х с параметром
--harmony
function main(){
async(function* (){
console.log('begin');
console.log(yield sleep(100));
console.log(yield sleep(200));
console.log(yield sleep(300));
console.log(yield sleep(400));
console.log(yield sleep(500));
console.log(yield sleep(600));
console.log(yield sleep(700));
console.log('end');
yield sleep(800)
return 'very end';
}).then(function(value){
console.log(value);
});
}
function async(coroutineFn){
var coroutine = coroutineFn();
function next(previous){
var result = coroutine.next(previous);
var current = Promise.resolve(result.value);
if(result.done)
return current;
return current
.then(function(value){
return next(value);
});
}
return next(void 0);
}
function sleep(delay){
return new Promise(function(succeed, failure){
setTimeout(function(){
succeed(delay);
}, delay);
});
}
main();
Здравствуйте, Ikemefula, Вы писали:
I>Промисы и есть многословно и прозрачно. При желании можно всё унутре спрятать.
ИМХО, тут нельзя сказать, что все прозрачно. Выглядит как некий альтернативный поток исполнения, но, скорее всего, со своими приблудами.
ARK>>>>Есть ли смысл в монадах для императивных языков? I>>>Еще пример — изолированая работа с состоянием.
I>Нет конечно. Попробуй реализовать абсолютно иммутабельный стек. Это никакая не монада. I>Когда найдешь способ, как же работать с таким стеком, ты изобретёшь монаду — отделение флоу от состояния.
Ну я знаю, как делаются иммутабельные стеки. И даже очереди. Но причем тут монады, не пойму.
Здравствуйте, AlexRK, Вы писали:
I>>Промисы и есть многословно и прозрачно. При желании можно всё унутре спрятать.
ARK>ИМХО, тут нельзя сказать, что все прозрачно. Выглядит как некий альтернативный поток исполнения, но, скорее всего, со своими приблудами.
Именно. Потому что это асинхронный код. С колбеками в общем случае проще не будет.
I>>Нет конечно. Попробуй реализовать абсолютно иммутабельный стек. Это никакая не монада. I>>Когда найдешь способ, как же работать с таким стеком, ты изобретёшь монаду — отделение флоу от состояния.
ARK>Ну я знаю, как делаются иммутабельные стеки. И даже очереди. Но причем тут монады, не пойму.
Еще раз — иммутабельный стек это НЕ монада.
монада понадобится в том случае, когда ты захочешь заюзать такой стек вместо обычного и убрать весь лишний код.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>[/haskell]Не очень удобно, правда? EP>Для упрощения синтаксиса и была введена do-нотация: EP>На C++ и код с проверками не нужен — можно использовать "встроенную монаду" исключение.
Я так понимаю, что Haskell героически борется с проблемами, которые сам себе и создал.
А кроме задания последовательности для ввода-вывода и исключений (которые в императивные языки встроены и воспринимаются как нечто само собой разумеющееся) есть какие-то вещи, которые могли бы пригодиться и в императивщине?
Здравствуйте, Ikemefula, Вы писали:
I>Еще раз — иммутабельный стек это НЕ монада. I>монада понадобится в том случае, когда ты захочешь заюзать такой стек вместо обычного и убрать весь лишний код.
А, понятно.
ИМХО, тут надо не монады применять, а скорее те же макросы — как я понял, монады все равно привносят грязь в код своими "нотациями".
С моей точки зрения было бы гораздо лучше, если бы я пометил иммутабельный стек специальным атрибутом, а компилятор по этому атрибуту нагенерил нужный код. При этом в месте вызова _ничего_ бы не указывало на то, что стек иммутабельный.
Здравствуйте, AlexRK, Вы писали:
EP>>[/haskell]Не очень удобно, правда? EP>>Для упрощения синтаксиса и была введена do-нотация: EP>>На C++ и код с проверками не нужен — можно использовать "встроенную монаду" исключение. ARK>Я так понимаю, что Haskell героически борется с проблемами, которые сам себе и создал.
Отчасти так и есть. Например есть монады для работы с изменяемыми переменными, массивами, циклами типа while и т.п.
ARK>А кроме задания последовательности для ввода-вывода и исключений (которые в императивные языки встроены и воспринимаются как нечто само собой разумеющееся) есть какие-то вещи, которые могли бы пригодиться и в императивщине?
Например монады для упрощения работы с асинхронностью, хотя и тут появляются некоторые аналоги типа await.
Из реально интересного — реализация software transactional memory на монадах. Хотя конечно можно и без явных монад.
Также монады полезны тем, что помогают локализовать те или иные эффекты. То есть взглянув только на сигнатуру функции, сразу понятно что она использует IO (не считая хаков типа unsafePerformIO), или кидает исключение и т.п.
Также интересный пример применения монад — парсинг, хотя опять таки реализуется и без монад (тот же Boost.Spirit).
Здравствуйте, AlexRK, Вы писали:
ARK>Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>[/haskell]Не очень удобно, правда? EP>>Для упрощения синтаксиса и была введена do-нотация: EP>>На C++ и код с проверками не нужен — можно использовать "встроенную монаду" исключение.
ARK>Я так понимаю, что Haskell героически борется с проблемами, которые сам себе и создал. ARK>А кроме задания последовательности для ввода-вывода и исключений (которые в императивные языки встроены и воспринимаются как нечто само собой разумеющееся) есть какие-то вещи, которые могли бы пригодиться и в императивщине?
Ну вот в Си исключений нет, только возвращаемые значения (и глобальные переменные, которые зло).
И в Хаскеле исключений нет, там тоже только возвращаемые значения.
Но в Хаскеле есть монады, которые позволяют убрать под капот что угодно, включая проверку-с-остановкой возвращенных значений (причем это будет делаться автоматически и проигнорировать/забыть обработать будет невозможно).
А в Си тебе разве что текстовыми макросами придется пользоваться (а вот монады строго типизированы).
А, например, асинхронщины (через колбэки) и в С++ нет встроенной, не только в Си и Хаскеле. Но, опять же, в Хаскеле это можно убрать под монадный капот, а в Си/С++03 придется объявлять гору функций и всюду передавать указатели на них (в С++11 — лямбды, что улучшает локальность кода, но все равно все кишки наружу).
То есть монады позволяют убрать под капот многие стратегии вычислений и оставить только суть (как это делают, например, исключения, по сравнению с кодом, проверяющим возвращаемые значения).
Тем и полезны.
Здравствуйте, jazzer, Вы писали:
J>А, например, асинхронщины (через колбэки) и в С++ нет встроенной, не только в Си и Хаскеле. Но, опять же, в Хаскеле это можно убрать под монадный капот, а в Си/С++03 придется объявлять гору функций и всюду передавать указатели на них (в С++11 — лямбды, что улучшает локальность кода, но все равно все кишки наружу). J>То есть монады позволяют убрать под капот многие стратегии вычислений и оставить только суть (как это делают, например, исключения, по сравнению с кодом, проверяющим возвращаемые значения). J>Тем и полезны.
Интересны примеры полезных монад, но для которых пока нет удобных аналогов в императивных языках. Для асинхронности есть coroutine/fiber/await/yield/etc.
И, кстати, если брать обобщённые сопроцедуры — call-with-current-continuation, то это даже более мощный инструмент чем do-нотация.
Так как для монадизации кода через do-нотацию его фактически нужно переписывать, а для монадизации через call/cc достаточно нескольких локальных изменений (либо вообще без изменений — зависит от языка). Пример вот тут
Здравствуйте, AlexRK, Вы писали:
ARK>Или монады это такая сложная концепция, что описать ее доступным языком невозможно в принципе?
Недавно я тупо прочитал статью по монадам в википедии, и там всё очень даже хорошо и понятно описано. В кратце идею можно передать достаточно просто:
The general monad concept includes any situation where the programmer wants to carry out a purely functional computation while a related computation is carried out on the side.
А дальше уже это дело обвешивается деталями в зависимости от конкретного языка.
Здравствуйте, BrainSlug, Вы писали:
J>>1. Уменьшить писанину J>>2. У функциональных языках нет никакого другого способа сделать именно последовательное выполнение, кроме вложенного вызова (очевидно, что надо выполнить вложенный вызов, прежде чем использовать его результат в вызывающей функции). Вот чтоб все эти вложенные вызовы не писать многоэтажно, придумали специальный конструкт — монада, где все это будет спрятано. J>>(ввод-вывод — это просто пример) BS>это, конечно, так, но мне казалось придумали для декомпозиции вычислений, на pure и не pure.
Ну есть же монады List, Identity... вполне pure в смысле отсутствия побочных эффектов.
А для чего их исторически придумали — хз. Вполне возможно, что и для того, что ты пишешь.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Например монады для упрощения работы с асинхронностью, хотя и тут появляются некоторые аналоги типа await. EP>Из реально интересного — реализация software transactional memory на монадах. Хотя конечно можно и без явных монад. EP>Также монады полезны тем, что помогают локализовать те или иные эффекты. То есть взглянув только на сигнатуру функции, сразу понятно что она использует IO (не считая хаков типа unsafePerformIO), или кидает исключение и т.п. EP>Также интересный пример применения монад — парсинг, хотя опять таки реализуется и без монад (тот же Boost.Spirit).
Вот то-то и оно — все полезное и без монад уже реализовано.
У меня пока складывается впечатление, что монады могут быть заменены кодогенерацией — причем с лучшим результатом, без всяких нотаций и т.п.
Здравствуйте, AlexRK, Вы писали:
ARK>ИМХО, тут надо не монады применять, а скорее те же макросы — как я понял, монады все равно привносят грязь в код своими "нотациями". ARK>С моей точки зрения было бы гораздо лучше, если бы я пометил иммутабельный стек специальным атрибутом, а компилятор по этому атрибуту нагенерил нужный код. При этом в месте вызова _ничего_ бы не указывало на то, что стек иммутабельный.
Так оно и есть. Проблема в том, что все монады в язык не всунешь, а скажем макрописатели из тех что ближе, исписались — было 50 контрибуторов, а стало полтора коммита в месяц.
Здравствуйте, AlexRK, Вы писали:
ARK>Вот то-то и оно — все полезное и без монад уже реализовано.
Один нюанс: оно все реализовано очень по-разному, а когда монады выражены через систему типов единообразно, можно писать универсальный код, работающий с произвольными монадами.
Здравствуйте, AlexRK, Вы писали:
ARK>У меня пока складывается впечатление, что монады могут быть заменены кодогенерацией — причем с лучшим результатом, без всяких нотаций и т.п.
Ха, так можно взять голый C и сказать что любую недостающую фичу можно заменить кодогенерацией
Здравствуйте, D. Mon, Вы писали:
ARK>>Вот то-то и оно — все полезное и без монад уже реализовано. DM>Один нюанс: оно все реализовано очень по-разному, а когда монады выражены через систему типов единообразно, можно писать универсальный код, работающий с произвольными монадами.
Звучит хорошо, но хотелось бы конкретный пример.
Ситуация напоминает ситуацию с функциональным программированием в целом. Сколько я уже читал басен про то, как все там прекрасно. Доходишь до примера — на тебе функцию Фибоначчи. Приведите, блин, код чтения-записи в файлы, генерации веб-страниц, работы с БД.
Вот и сейчас я не очень пойму — какой реальный код может быть написан, чтобы единообразно работать с монадой "последовательность вызовов" и монадой "исключение"? Что этот код делает и зачем он нужен?
Здравствуйте, Evgeny.Panasyuk, Вы писали:
ARK>>У меня пока складывается впечатление, что монады могут быть заменены кодогенерацией — причем с лучшим результатом, без всяких нотаций и т.п. EP>Ха, так можно взять голый C и сказать что любую недостающую фичу можно заменить кодогенерацией
Если кодогенерация более удобна в использовании, чем встроенные фичи — то почему бы и нет?
Я всегда считал, что встроенная фича должна быть на порядок проще и удобнее, чем невстроенная (иначе нафига ее встраивать?).
Кодогенерация проще, чем встроенные классы? Вряд ли (оставим вопросы гибкости за бортом). Проще, чем встроенные исключения? Тоже вряд ли.
А вот с встроенными монадами как-то все уже не очень очевидно.
Здравствуйте, AlexRK, Вы писали:
ARK>Звучит хорошо, но хотелось бы конкретный пример.
ARK>Ситуация напоминает ситуацию с функциональным программированием в целом. Сколько я уже читал басен про то, как все там прекрасно. Доходишь до примера — на тебе функцию Фибоначчи. Приведите, блин, код чтения-записи в файлы, генерации веб-страниц, работы с БД.
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, AlexRK, Вы писали:
ARK>>Может кто-нибудь описать простым языком — что такое монады и зачем они нужны?
Pzz>http://rsdn.ru/forum/philosophy/2340340
Нет, это явно не "простой язык".
Что такое линейные/уникальные типы я знаю, а все остальное мимо.
а дальше идут monad transformers, которые представляют не просто одну монаду, а способ добавить к монаде новую функциональность. т.е. ввам не придётся например выбирать между Error monad (прекразает вычисление при возбуждении ошибки), State monad, Parsing monad (сохраняет текущее состояние бибилиотеки парсинга), а вы их можете объединить вместе, наслоив одну на другую и использовать всю необходимую вам функциональность в общем коде. более того, вы можете добавить в этот бутерброд новые монады по мере развития программы, а эта запись do с вызываемыми в ней процедурами останется неизменной
По-хорошему, хотелось бы простых примеров, причем не на хаскелле, а на паскалеподобном псевдокоде (как в википедии алгоритмы описаны). Однако понимаю, что этого никто делать не будет.