http://ru.wikipedia.org/wiki/%D0%9C%D0%BE%D0%BD%D0%B0%D0%B4%D0%B0_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
Может быть кто-то расскажет мне про монады?
Идею я примерно понимаю.
Но вот - технические тонкости - что-то не схватываю.
Есть кому, что рассказать? Для "технарей".
С примерами из реальной жизни.
P.S. понятно, что функция - детерминирована относительно её параметров, а монада - нет. И что функцию можно даже кешировать относительно значений её параметров.
P.P.S. Любая глобальная переменная или ввод-вывод это монады? А функция использующая хотя бы одну монаду - тоже монада? Ну по индукции. А значит, что любая "программа" на функциональном языке использующая хотя бы одну монаду - тоже монада? Ну тоже по индукции.. Так?
P.P.P.S. Функция, зависящая от даты/времени - тоже монада?
Может быть кто-то расскажет мне про монады?
Идею я примерно понимаю.
Но вот - технические тонкости - что-то не схватываю.
Есть кому, что рассказать? Для "технарей".
С примерами из реальной жизни.
P.S. понятно, что функция - детерминирована относительно её параметров, а монада - нет. И что функцию можно даже кешировать относительно значений её параметров.
P.P.S. Любая глобальная переменная или ввод-вывод это монады? А функция использующая хотя бы одну монаду - тоже монада? Ну по индукции. А значит, что любая "программа" на функциональном языке использующая хотя бы одну монаду - тоже монада? Ну тоже по индукции.. Так?
P.P.P.S. Функция, зависящая от даты/времени - тоже монада?
Монаду нельзя сравнивать с функцией - это совсем не функция. И кэшируемость зависит от самой монады.
ОтветитьУдалитьМонады(в хаскеле) это такой класс объектов, определённых следующими функциями:
1) (>>) :: Monad m => m a -> m b -> m b
Т.е связывание, при котором значение первой монады игнорируется.
2) (>>=) :: Monad m => m a -> (a -> m b) -> m b
Т.е связывание, при котором значение из монады 1 передаётся функции, возвращающей монаду 2.
3) return :: Monad m => a -> m a
Т.е функция, создающая монаду из значения.
Ещё есть доп. Функция fail.
На основании этих функций монады взаимодействуют между собой, и этим функциям доступно кэширование(монада выступает как один из аргументов этих функций).
Особый случай - монады ST и IO, они специальным образом обрабатываются компилятором.
Любая "глобальная переменная" это монада, функция использующая монады не обязательно монадическая, т.к некоторые монады предусматривают получение значаения(Монады [a], Maybe a, например). В функциональных языках функции не считаются программами или подпрограммами. Если говорить о монаде IO - то да, честного выхода из неё нет, и все функции работающие с ней должны быть монадическими.
Про дату и время - всё зависит от того, как построена зависимость(может параметр даты и времени передаётся снаружи).
Что-либо ещё смогу написать только вечером =)
Простите, но первую часть - вообще не понимаю.
УдалитьМожно по-русски? На бытовом уровне. Для тупых. А не в закорючках?
УдалитьВ закорючках - я уже читал :-) И не раз.
"В функциональных языках функции не считаются программами или подпрограммами"
Удалить"Вы на воздушном шаре"
И что? Какая разница - что чем "считается". Гораздо важнее, что чем - ЯВЛЯЕТСЯ.
Фунукции в ФП действительно не являются подпрограммами. В императивном языке вы работаете с подпрограммами, компилятор не имеет права превратить код во что-либо другое. Хотя он это и делает, но это "обман", и некоторые оптимизации для него не позволительны. В ФП функция это отображение из 'a' в 'b', и совершенно не важно как оно произойдёт, главное что бы оно подчинялось описаным правилам. В реальности вызова функции может и не быть, а для "манёвров" компилятора остаётся максимум места.
Удалить
ОтветитьУдалитьДело тут, похоже, не в чьей-то "тупизне", а в моей неспособности объяснить простым языком. =(
Ладно, попробую ещё раз:
Начнём с того что монада это класс типов. Это означает что для всех типов этого класса определены некоторые функции(можно провести аналогию с "интерфейсом" в ООП). Надеюсь тут всё понятно?
Далее: монада это не обычный "интерфейс", его можно представить как "шаблонный интерфейс" параметризуемый одним параметром.
IO String - монада с типом String, например.
IO Int - монада с типом Int
[Bool] - монада с типом Bool,
Maybe Int - монада с типом Int.
итд.
Далее: что за функции определены в "интерфейсе" монады? Есть три основные функции(одну дополнительную опустим):
1) Функция ">>". Она берёт две монады(одного типа, IO, например) и возвращает третью монаду того же типа.
При этом первая и вторая монада могут быть "параметризованы" различными типами, останется только параметр-значение второй.
Например IO Int >> IO String будет IO String.
2) Функция ">>=". Производит "связывание" монады и монадической функции. Монадическая функция - это такая функция, которая возвращает монаду.
Допустим у нас есть функция String -> IO (). Т.е функция принимает строку, и возвращает пустую монаду. Так, например, поступает функция вывода в консоль.
И у нас есть монада IO String. Так, например, выглядит монада читающая строку из консоли. Связывание "исполняет" монадическую функцию, используя значение из монады.
IO String >> (String -> IO ()) будет IO ().
Т.е getLine >>= putStrLn, выведет строку, полученную из ввода. Т.к getLine это монада (IO String), а putStrLn это монадическая функция (String -> IO () ). Скобки () означают пустое значение.
3) Функция "return". Функция предельно простая - она помещает значение в монаду. Т.е return 1 для IO вернёт IO Int,
для списка - [Int], для Maybe - Maybe Int.
Впрочем, не думаю что это объяснение намного лучше предыдущего. Но надеюсь вы хоть общее представление получили. =)
Спасибо. Вот тут - есть над чем подумать.
УдалитьЯ правильно понимаю, что монада это "хинт" компилятору, что "тут начинается недетерминированная зона"?
УдалитьС точки зрения хаскеля("категории hask") монады - это обычный класс типов. Компилятор обрабатывает специальным образом только "IO" и "ST", другие монады он не трогает. =)
УдалитьНе очень понимаю - как компилятор может их "не трогать" - ему же важна детерминированность функций. Или я ошибаюсь?
УдалитьСцепки "монада - монада". Без выхода. Понимаю. Но "монада - функция". Не понимаю.
УдалитьПовторю вопрос - что компилятор делает со сцепками "монада - функция"? Или "функция - монада"?
УдалитьНа "бытовом уровне". Считали из файла (который недетерминированный). Получили значение. Передаём в функцию. Она детерминирована?
Что с ней делает компилятор? "Изолирует" от детерминированных функций?
Сами по себе монады детерминированны. Монады это просто описание. В случае IO можно сказать что хаскель строит описание действий программы. Компилятор в последствии создаёт из этого описания программу. Т.е с точки зрения хаскеля IO a >> IO b это вполне себе детерминированная функция.
УдалитьОбычно соединение монады и монадической функции выглядит так: после того как будет выяснено значение монады, оно будет передано функции, которая вернёт ещё одну монаду. А там они уже радостно соединятся как монада - монада. =)
Монадическая функция служит только для создания монады.
Ничего не понял...
УдалитьА можно пример из реальной жизни? В духе - вот есть задача - вот так её решаем.
Можно. Вот написал парсер конфигураций. Конфигурации представляют собой пары название := значение. В роли значений могут выступать либо строки либо другие конфигурации, указаные в фигурных скобках. Например:
Удалитьname1 := "string value";
name2 := "string value2";
name3 := {
name3a := "string value3a";
name3b := "string value3b";
};
Код с комментариями, хотя по мне - они лишние.
http://pastebin.com/tEiqGVwH
Это, собственно, пример монады как описания. Т.е сама по себе монада Parser ничего не парсит. Парсит функция "parseTest", используя описание, предоставленное монадой.
Мда. "Не убедил".
УдалитьНе в этой жизни видимо.... :-(
В каком плане "не убедил"? У вас есть более выразительные средства для подобного рода операций? Я бы не прочь ознакомиться. =)
УдалитьДля того, чтобы обсуждать "подобного рода" - надо понимать что там написано. Это во-первых. Китайский язык - может быть и занятен. Но явно - не ВЫРАЗИТЕЛЕН. По-моему вы всё-таки путаете ВЫРАЗИТЕЛЬНОСТЬ с КОМПАКТНОСТЬЮ. Это - не то же самое. Во-вторых - использовать библиотеки - я тоже могу. В ЛЮБОМ языке. В-третьих - так я и не понял - что такое монады и как введение этого понятия помогает нефункциональным вещам стать функциональными. Иначе - непонятно - зачем изобретать какие-то дополнительные понятия.
УдалитьА вы не понимаете что там написано? Прочитайте описание выше. И, поверьте мне, если бы я хотел компактности, я бы записал компактно(http://pastebin.com/8Sc26dg1). А данный код выигрывает именно по читаемости. Вообще мне сложно представить более читаемый код. Может изобразите? =)
УдалитьИ я же не говорил что вы не можете использовать библиотеки?
Монада это не дополнительное понятие. Это такое же понятие как "коллекция", "итератор", итд. А помогает она тем, что может просто описать императивность, последовательность действий. Но именно описать, а не совершить.
Да я понимаю, что там написано.
УдалитьНо всё равно - разговор слепого с глухим.
"Может изобразите?" - типа на слабо? Нет, не изображу. Я не привык - на слабо.
Да и я лично продолжаю считать это "набором закорючек". Удивляюсь я. Зачем люди придумывают себе сложности, а потом героически их преодолевают. А потом рассказывают, что "это выразительно".
НЕ выразительно.
В общем - про монады - не рассказали :-(
>"Может изобразите?" - типа на слабо? Нет, не изображу. Я не привык - на слабо.
УдалитьНа самом деле я специально выбрал для примера парсинг текста, т.к считаю что у вас в этом деле много опыта. Ну что ж - коль не хотите, это ваше дело. Никто вас не заставляет, и никто не хочет отнимать у вас время. =)
>В общем - про монады - не рассказали :-(
Ну, я хотя бы попробовал. =)
Спасибо конечно. Попытались.
УдалитьЕсли уж про "парсеры" и выразительность, то по-моему выразительнее БНФ - никто пока ничего не придумал.
Пример декларативности по-моему - yacc/lexx. Хотя есть у меня к ним вопросы.
Как видите - придумали. =)
УдалитьПо мне - БНФ - нагляднее.
УдалитьНо к монадам - я ещё вернусь. Жаль не знаю координат собеседника :-)
Вы меня кстати - простите за резкость, если что. Меня просто иногда бесит - когда люди банальные для них вещи - не могут объяснить мне. Но это - мои проблемы. Я с ними - борюсь.
УдалитьПо-моему - я что-то понял - http://18delphi.blogspot.com/2013/10/blog-post_21.html
ОтветитьУдалитьВопрос - ПРАВИЛЬНО ли я понял?