Монады
От: AlexRK  
Дата: 26.10.14 19:20
Оценка: :))) :)
Товарищи!

Может кто-нибудь описать простым языком — что такое монады и зачем они нужны?

Сколько ни видел в интернете трудов наподобие "простое описание монад" — никто не может описать доходчиво. Везде одна и та же хрень: "я понял монады!" и начинается "это тип с операциями bind и return", бла-бла-бла.

Или монады это такая сложная концепция, что описать ее доступным языком невозможно в принципе?
Re: Монады
От: dimgel Россия https://github.com/dimgel
Дата: 26.10.14 19:22
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Может кто-нибудь описать простым языком — что такое монады и зачем они нужны?


Вот же, тремя ветками ниже уже с полгода обсуждают: http://rsdn.ru/forum/philosophy/5380969
Автор: dimgel
Дата: 03.12.13
Re: Монады
От: jazzer Россия Skype: enerjazzer
Дата: 26.10.14 19:27
Оценка: +1
Здравствуйте, AlexRK, Вы писали:

ARK>Товарищи!


ARK>Может кто-нибудь описать простым языком — что такое монады и зачем они нужны?


ARK>Сколько ни видел в интернете трудов наподобие "простое описание монад" — никто не может описать доходчиво. Везде одна и та же хрень: "я понял монады!" и начинается "это тип с операциями bind и return", бла-бла-бла.


ARK>Или монады это такая сложная концепция, что описать ее доступным языком невозможно в принципе?


Это способ связать вычисления каким-либо образом. Паттерн, если угодно. Выраженный прямо в языке.
Например, строго последовательное вычисление (сюда же и ввод-вывод, так как он задает последовательность естественным образом).
Или continuation-passing.
Или непродолжение в случае ошибки в одном из предыдущих вычислений.
Или вывалить в виде списка.
В общем, что душе угодно.

То, как именно осуществляется эта связь, кодируется в функции bind. Что ты там накодируешь — такая монада и получится.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Монады
От: AlexRK  
Дата: 26.10.14 19:28
Оценка:
Здравствуйте, dimgel, Вы писали:

D>Вот же, тремя ветками ниже уже с полгода обсуждают: http://rsdn.ru/forum/philosophy/5380969
Автор: dimgel
Дата: 03.12.13


Во-во, яркий пример того, о чем я и говорил. На первых 5 страницах — ни одного нормального объяснения.
Re[3]: Монады
От: jazzer Россия Skype: enerjazzer
Дата: 26.10.14 19:33
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, dimgel, Вы писали:


D>>Вот же, тремя ветками ниже уже с полгода обсуждают: http://rsdn.ru/forum/philosophy/5380969
Автор: dimgel
Дата: 03.12.13


ARK>Во-во, яркий пример того, о чем я и говорил. На первых 5 страницах — ни одного нормального объяснения.


Вот такое объяснение тебе нормально?
http://rsdn.ru/forum/philosophy/5392303.1
Автор: jazzer
Дата: 11.12.13


А вообще — отсортируй ту ветку по оценкам, там куча объяснений на любой вкус.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Монады
От: AlexRK  
Дата: 26.10.14 19:34
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Это способ связать вычисления каким-либо образом. Паттерн, если угодно. Выраженный прямо в языке.

J>Например, строго последовательное вычисление (сюда же и ввод-вывод, так как он задает последовательность естественным образом).
J>Или continuation-passing.
J>Или непродолжение в случае ошибки в одном из предыдущих вычислений.
J>Или вывалить в виде списка.
J>В общем, что душе угодно.

А зачем это нужно? Насколько мне известно, монады есть далеко не во всех даже функциональных языках.
Ввод-вывод можно и безо всяких монад выполнять последовательно в том порядке, в каком он записан.
Есть ли смысл в монадах для императивных языков?
Re[4]: Монады
От: AlexRK  
Дата: 26.10.14 19:38
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Вот такое объяснение тебе нормально?

J>http://rsdn.ru/forum/philosophy/5392303.1
Автор: jazzer
Дата: 11.12.13


Да, это мне понятно. Но непонятно, как может выглядеть реализация этого.

Это похоже на "ты пишешь код, как будто дедлоков нет, но компилятор все отслеживает и не дает скомпилировать программу, если обнаружит дедлоки". То есть звучит все круто, но как это сделано?
Re[3]: Монады
От: jazzer Россия Skype: enerjazzer
Дата: 26.10.14 19:40
Оценка: 63 (3) +1
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, jazzer, Вы писали:


J>>Это способ связать вычисления каким-либо образом. Паттерн, если угодно. Выраженный прямо в языке.

J>>Например, строго последовательное вычисление (сюда же и ввод-вывод, так как он задает последовательность естественным образом).
J>>Или continuation-passing.
J>>Или непродолжение в случае ошибки в одном из предыдущих вычислений.
J>>Или вывалить в виде списка.
J>>В общем, что душе угодно.

ARK>А зачем это нужно? Насколько мне известно, монады есть далеко не во всех даже функциональных языках.

ARK>Ввод-вывод можно и безо всяких монад выполнять последовательно в том порядке, в каком он записан.
1. Уменьшить писанину
2. У функциональных языках нет никакого другого способа сделать именно последовательное выполнение, кроме вложенного вызова (очевидно, что надо выполнить вложенный вызов, прежде чем использовать его результат в вызывающей функции). Вот чтоб все эти вложенные вызовы не писать многоэтажно, придумали специальный конструкт — монада, где все это будет спрятано.
(ввод-вывод — это просто пример)

ARK>Есть ли смысл в монадах для императивных языков?


Ну вот я рядом привел пример
Автор: jazzer
Дата: 11.12.13
автоматической проверки errno и прерывания исполнения функции, если что не так — стандартная сишная задача. Если бы были монады — можно было бы спрятать это внутрь оной и код стал бы на порядок чище.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Монады
От: jazzer Россия Skype: enerjazzer
Дата: 26.10.14 19:46
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, jazzer, Вы писали:


J>>Вот такое объяснение тебе нормально?

J>>http://rsdn.ru/forum/philosophy/5392303.1
Автор: jazzer
Дата: 11.12.13


ARK>Да, это мне понятно. Но непонятно, как может выглядеть реализация этого.


ARK>Это похоже на "ты пишешь код, как будто дедлоков нет, но компилятор все отслеживает и не дает скомпилировать программу, если обнаружит дедлоки". То есть звучит все круто, но как это сделано?


все превращается во вложенные вызовы вложенных лябмд, по условию errno.
Ты это и сам пишешь в Си руками в виде многоэтажных ифов, монады просто позволяют это дело упрятать под капот.
Т.е. проверка errno и продолжение вычислений на основании его значения — это паттерн (синтаксический, если угодно).
Монада позволяет кишки этого паттерна спрятать.
Только и всего.
Никакого волшебства и зауми.

То есть всегда, когда у тебя в обычном языке есть несколько инструкций, которые друг с другом как-то связаны, и эта связь выражена одинаково (как в случае с errno) — ты можешь кишки, которыми закодирована эта связь, убрать с глаз долой внутрь монады. Независимо от характера связи. Вот и все.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Отредактировано 26.10.2014 19:49 jazzer . Предыдущая версия .
Re[4]: Монады
От: AlexRK  
Дата: 26.10.14 19:46
Оценка:
Здравствуйте, jazzer, Вы писали:

J>2. У функциональных языках нет никакого другого способа сделать именно последовательное выполнение, кроме вложенного вызова (очевидно, что надо выполнить вложенный вызов, прежде чем использовать его результат в вызывающей функции).


Если язык ленивый — то не факт, что вложенный вызов будет исполнен раньше, чем невложенный.

J>Ну вот я рядом привел пример
Автор: jazzer
Дата: 11.12.13
автоматической проверки errno и прерывания исполнения функции, если что не так — стандартная сишная задача. Если бы были монады — можно было бы спрятать это внутрь оной и код стал бы на порядок чище.


А как бы это могло выглядеть на С/C++? Нужны были бы новые синтаксические конструкции?

И еще я не пойму границ применимости этой концепции. Можно ли монадами сделать логгирование в начале и конце метода?
Re[5]: Монады
От: jazzer Россия Skype: enerjazzer
Дата: 26.10.14 19:56
Оценка: 8 (1)
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, jazzer, Вы писали:


J>>2. У функциональных языках нет никакого другого способа сделать именно последовательное выполнение, кроме вложенного вызова (очевидно, что надо выполнить вложенный вызов, прежде чем использовать его результат в вызывающей функции).


ARK>Если язык ленивый — то не факт, что вложенный вызов будет исполнен раньше, чем невложенный.


Как ты можешь получить результат выражения до того, как вычислил все его подвыражения (при условии, что все подвыражения используются, ессно)?
Если у тебя f()+g() — ты не можешь получить результат (сумму) раньше, чем будут вычислены оба подвыражения f() и g().
Ленивость лишь определяет, когда ты получишь и то, и другое, но порядок (иерархия) вычисления от ленивости не изменится.

J>>Ну вот я рядом привел пример
Автор: jazzer
Дата: 11.12.13
автоматической проверки errno и прерывания исполнения функции, если что не так — стандартная сишная задача. Если бы были монады — можно было бы спрятать это внутрь оной и код стал бы на порядок чище.


ARK>А как бы это могло выглядеть на С/C++? Нужны были бы новые синтаксические конструкции?


Да. И в Хаскеле тоже — там для этого есть специальная do notation, и она там, вроде как, тоже далеко не сразу появилась.

ARK>И еще я не пойму границ применимости этой концепции. Можно ли монадами сделать логгирование в начале и конце метода?


Монады относятся к организации вызовов. Так что логирование каждой строчки твоей функции (в функциональном языке это вызовы функций) — да. Или там профилирование.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Монады
От: BrainSlug Израиль  
Дата: 26.10.14 19:58
Оценка:
J>1. Уменьшить писанину
J>2. У функциональных языках нет никакого другого способа сделать именно последовательное выполнение, кроме вложенного вызова (очевидно, что надо выполнить вложенный вызов, прежде чем использовать его результат в вызывающей функции). Вот чтоб все эти вложенные вызовы не писать многоэтажно, придумали специальный конструкт — монада, где все это будет спрятано.
J>(ввод-вывод — это просто пример)
это, конечно, так, но мне казалось придумали для декомпозиции вычислений, на pure и не pure.
.
Re[5]: Монады
От: Evgeny.Panasyuk Россия  
Дата: 26.10.14 20:14
Оценка: 8 (1)
Здравствуйте, AlexRK, Вы писали:

J>>2. У функциональных языках нет никакого другого способа сделать именно последовательное выполнение, кроме вложенного вызова (очевидно, что надо выполнить вложенный вызов, прежде чем использовать его результат в вызывающей функции).

ARK>Если язык ленивый — то не факт, что вложенный вызов будет исполнен раньше, чем невложенный.

Там, грубо говоря, вывод делает не сам вызов, а его результат. И вот эти результаты как раз выстраиваются в жёсткую последовательность.
Если ты просто где-то сделаешь вызов с выводом, не передав его результат в соответствующую монаду, то никакого вывода не будет.

J>>Ну вот я рядом привел пример
Автор: jazzer
Дата: 11.12.13
автоматической проверки errno и прерывания исполнения функции, если что не так — стандартная сишная задача. Если бы были монады — можно было бы спрятать это внутрь оной и код стал бы на порядок чище.

ARK>А как бы это могло выглядеть на С/C++? Нужны были бы новые синтаксические конструкции?

Специальные синтаксические конструкции нужны только для удобства, например do-нотация. Монады-же можно использовать и без do-notation.
А вот один из вариантов того, как можно сделать do-нотацию в C++:
DO(Monad,
    (x, unit(1))
    (y, unit(2))
    (z, DO(Monad,
        (x, unit(5))
        (_, unit(x - 2))
    ))
    (_, unit(x + y + z))
)
Re: Монады
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.10.14 20:17
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Может кто-нибудь описать простым языком — что такое монады и зачем они нужны?


ARK>Сколько ни видел в интернете трудов наподобие "простое описание монад" — никто не может описать доходчиво. Везде одна и та же хрень: "я понял монады!" и начинается "это тип с операциями bind и return", бла-бла-бла.


Простым языком это не получится сделать. Скажем, тот же интеграл будет очень сложно объяснить тому, кто график функции никогда не строил. Монады растут из теории категорий, которую мало кто понимает.

ARK>Или монады это такая сложная концепция, что описать ее доступным языком невозможно в принципе?


Монады это способ управления отдельными аспектами конкретной логики. Например можно изолировать флоу от эффекта и тд. Эффект — изменение состояния, временая задержка и тд.
Был, скажем, синхронный код — с помощью монады можно получить такой код, который будет синхронным или асинхронным в зависимости от вызывающего кода. Здесь отделяется флоу от временной задержки.

P.S. Теоретически, это можно сделать и без монад. Практически — все равно получится монадическая сущность.
Re[6]: Монады
От: AlexRK  
Дата: 26.10.14 20:22
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Там, грубо говоря, вывод делает не сам вызов, а его результат. И вот эти результаты как раз выстраиваются в жёсткую последовательность.

EP>Если ты просто где-то сделаешь вызов с выводом, не передав его результат в соответствующую монаду, то никакого вывода не будет.

А... тогда понятно.

EP>Специальные синтаксические конструкции нужны только для удобства, например do-нотация. Монады-же можно использовать и без do-notation.

EP>А вот один из вариантов того, как можно сделать do-нотацию в C++:
EP>
EP>DO(Monad,
EP>    (x, unit(1))
EP>    (y, unit(2))
EP>    (z, DO(Monad,
EP>        (x, unit(5))
EP>        (_, unit(x - 2))
EP>    ))
EP>    (_, unit(x + y + z))
EP>)
EP>


Нда... По-моему, код с проверками выглядит гораздо чище, чем это.
Re[6]: Монады
От: Evgeny.Panasyuk Россия  
Дата: 26.10.14 20:22
Оценка:
Здравствуйте, jazzer, Вы писали:

J>>>2. У функциональных языках нет никакого другого способа сделать именно последовательное выполнение, кроме вложенного вызова (очевидно, что надо выполнить вложенный вызов, прежде чем использовать его результат в вызывающей функции).

ARK>>Если язык ленивый — то не факт, что вложенный вызов будет исполнен раньше, чем невложенный.
J>Как ты можешь получить результат выражения до того, как вычислил все его подвыражения (при условии, что все подвыражения используются, ессно)?
J>Если у тебя f()+g() — ты не можешь получить результат (сумму) раньше, чем будут вычислены оба подвыражения f() и g().
J>Ленивость лишь определяет, когда ты получишь и то, и другое, но порядок (иерархия) вычисления от ленивости не изменится.

Там не в этом дело, сам вызов вывод не производит. Его результирующие значение представляет действие по совершению этого вывода.

Например, для монад есть такой оператор >>:
putStrLn "abc" >> putStrLn "def"

Который реализуется как:
m >> n     =      m >>= \_ -> n

Тут, вообще говоря, n может быть вычислено раньше чем m.
Re[3]: Монады
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.10.14 20:31
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>А зачем это нужно? Насколько мне известно, монады есть далеко не во всех даже функциональных языках.


Поддержка синтаксиса необязательна. хочешь хороший пример монады — посмотри Promise в джаваскрипте.

http://www.html5rocks.com/en/tutorials/es6/promises/

ARK>Ввод-вывод можно и безо всяких монад выполнять последовательно в том порядке, в каком он записан.

ARK>Есть ли смысл в монадах для императивных языков?

Есть. см ссылку выше. Еще пример — изолированая работа с состоянием.
В некоторых случаях вместо
stack.push(a)
...
stack.pop()


имеет смысл писать вот так —

var stack1 = push(stack0, a)
...
var (a,stackN) = pop(stackN-1)


Если хочется разобраться получше, начни с Promise в джаваскрипте и парсер-комбинаторов.
Re[4]: Монады
От: AlexRK  
Дата: 26.10.14 20:41
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Поддержка синтаксиса необязательна. хочешь хороший пример монады — посмотри Promise в джаваскрипте.

I>http://www.html5rocks.com/en/tutorials/es6/promises/

Посмотрел. Выглядит как ужасная грязь — даже на маленьких кусочках кода.
Страшно подумать, что будет на больших.

Лично мне нравится одно из двух: либо когда явно видно все, что происходит, пусть и многословно; либо когда абстракция полноценна и полностью скрывает все, что под капотом (например, асинхронный код выглядит и действует так же, как синхронный).

ARK>>Есть ли смысл в монадах для императивных языков?

I>Еще пример — изолированая работа с состоянием.

Это же вроде просто иммутабельные типы, нет?
Re[5]: Монады
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.10.14 20:50
Оценка:
Здравствуйте, AlexRK, Вы писали:

I>>Поддержка синтаксиса необязательна. хочешь хороший пример монады — посмотри Promise в джаваскрипте.

I>>http://www.html5rocks.com/en/tutorials/es6/promises/

ARK>Посмотрел. Выглядит как ужасная грязь — даже на маленьких кусочках кода.

ARK>Страшно подумать, что будет на больших.

Эту грязь может убрать только синтаксис встроеный в язык. Любая логика на колбеках превращается в адъ. Промисы значительно оттягивают такой конец.

ARK>Лично мне нравится одно из двух: либо когда явно видно все, что происходит, пусть и многословно; либо когда абстракция полноценна и полностью скрывает все, что под капотом (например, асинхронный код выглядит и действует так же, как синхронный).


Промисы и есть многословно и прозрачно. При желании можно всё унутре спрятать.

ARK>>>Есть ли смысл в монадах для императивных языков?

I>>Еще пример — изолированая работа с состоянием.

ARK>Это же вроде просто иммутабельные типы, нет?


Нет конечно. Попробуй реализовать абсолютно иммутабельный стек. Это никакая не монада.

Когда найдешь способ, как же работать с таким стеком, ты изобретёшь монаду — отделение флоу от состояния.
Re[7]: Монады
От: Evgeny.Panasyuk Россия  
Дата: 26.10.14 20:53
Оценка:
Здравствуйте, AlexRK, Вы писали:

EP>>Там, грубо говоря, вывод делает не сам вызов, а его результат. И вот эти результаты как раз выстраиваются в жёсткую последовательность.

EP>>Если ты просто где-то сделаешь вызов с выводом, не передав его результат в соответствующую монаду, то никакого вывода не будет.
ARK>А... тогда понятно.

Продолжая тему монады ввод/вывод:

Есть функция putStrLn, которая принимает строку, и результатом которой является действие по выводу этой строки.
Эти действия можно выстроить в цепочку, с помощью того самого bind'а:
putStrLn "abc" >>= (\unused_parameter -> putStrLn "def")
(где \x -> f x — это лямбда с одним параметром, и вызывающая f для этого параметра)

Далее, есть функция getLine — которая возвращает действие по считыванию строки.
Доступ к считанной строке можно получить (и вывести с помощью putStrLn) через тот самый bind:
getLine >>= (\string_from_user -> putStrLn string_from_user)


Теперь рассмотрим пример чуть сложнее, нужно считать две строки, склеить и вывести:
getLine >>= 
    (\first_string ->
        getLine >>=
            (\second_string ->
                putStrLn first_string ++ second_string
            )
    )
Не очень удобно, правда?
Для упрощения синтаксиса и была введена do-нотация:
do
    first_string <- getLine
    second_string <- getLine
    putStrLn first_string ++ second_string
этот imperative-like код механически переписывается в предыдущий пример.

ARK>Нда... По-моему, код с проверками выглядит гораздо чище, чем это.


На C++ и код с проверками не нужен — можно использовать "встроенную монаду" исключение.
А вот пригодится такая нотация может, например, при работе с монадой List.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.