Re[50]: Есть ли вещи, которые вы прницпиально не понимаете...
От: akava Беларусь kavaleu.ru
Дата: 13.01.14 18:44
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Ну так такое без проблем реализуется в языках, в которых доступна перегрузка операторов. Только вот к монадам это не имеет никакого отношения.

Все реализуется на ассемблере. Вопрос в количестве телодвижений. Какой объем работы нужно проделать, чтобы реализовать все эти операции для optional<>, future<>, ...?

A>>Я, кнечно, могу ошибаться, но я не вижу переколбашивания. Если у T есть сложение, умножение и сравнение, то функция работает. Монада же дает эти операции "на лету" функций над базовым типом.

_>Монада ничего подобного не даёт. Ну точнее она нам даёт автоматическую реализацию этих функций, но расставить их вызовы в коде надо руками.
Ты, наверное, имеешь ввиду расставить руками в Хаскеле. Так?
Но дело в том, что Монада -- математическая конструкция. Которая никак не привязана к Хаскелю и другим реализациям.
И ничего нам не помешает реализовать специальный язык Монаскель, в котором вручную ничего расставлять не придется, но мы огребем вохрох проблем
Автор: akava
Дата: 13.01.14
(и это только те, что вижу я).
Но даже сейчас, в Хаскеле, с помощью do-сахара нам, насколько я понял, не придется расставлять вызовы руками.

СУВ, akava





_>Поясняю разница в подходах:

_>1. Монады. Определяется ровно одна функция и всё. Дальше, с помощью неё можно разрулить абсолютно все ситуации (в этом и фокус как бы). Но вставлять эту функцию по коду надо руками.
_>2. Перегрузка операторов. Надо определить кучу операторов для каждого вида монады. И плюс возможно перегрузить несколько функций (те, которые определены не как шаблонные и соответственно не могут сами подхватить новый тип). Но зато после этого, никаких изменений в коде не потребуется вообще. Ни в одной букве.
Мы в философии. Мы можем фантазировать. Сделай, плиз, один шаг -- объедини 2 подхода.
Re[43]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 13.01.14 18:59
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Он короче, чем многословное решение на query comprehension. Решение на Хаскеле по краткости ты сильно вряд ли обгонишь, но я не могу его показать, Хаскелем не владею как то.


Да, скорее всего так и будет. Но у всего есть своя цена. И у Хаскеля она появляется в месте взаимодействия с реальным внешним миром...

I>Да, монады встроены в язык.


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

I>Чего ты хочешь объяснить, я уже не понимаю. Большей частью у тебя сравнение query comprehension С# vs императивный код на С++.


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

Насколько я помню, практические единственным реальным примером были как раз твои реактивные монадные парсеры. Из плюсов надо отметить, что это действительно работающий пример. Ну а из минусов (что мы тут и обсуждали) — как мы увидели, тоже самое можно реализовать и без монад, причём частенько и ещё проще. Так что это хотя и был реальный ответ на мой вопрос, но он не стал аргументом в пользу монад.
Re[50]: Есть ли вещи, которые вы прницпиально не понимаете...
От: akava Беларусь kavaleu.ru
Дата: 13.01.14 19:04
Оценка:
Здравствуйте, AlexRK, Вы писали:

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


A>>Да, на протяжении всей цепочки, за счет вывода типов, все значения обернутся в монады. Но в конце цепочки, где мы будем использовать результат (вызов вэбсервиса, например) компилятор ругнется и скажет, что такая-то функция не умеет работать с типом optional<T>.

ARK>Где-то может и уметь — совершенно случайно.
IQueriable в linq -- типичная монада.
В зависимости от реализации, она может и коллекцию итерировать, и в базу лезть, и вэбсервис вызывать, ... и эксепшены по делу и нет выкидывать. Это ведь никого не пугает.
Все, наоборот радуются, что один и тот же код может и "и коллекцию итерировать, и в базу лезть, и вэбсервис вызывать". А все это благодаря концепции Монада.

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

Вот как первый косяк из моего сообщения выше
Автор: akava
Дата: 13.01.14
решен в linq: http://dotnetfiddle.net/Kme3rI
var q = (new []{1, 2, 3}).AsQueryable().Where(i=>i%2 == 0);
Console.WriteLine(q); // выводит: System.Int32[].Where(i => ((i % 2) == 0))

Вполне годное решение.
Хотя при работе с linq ты знаешь, что работаешь с linq. Т.е. должен понимать, что в зависимости от реализации IQueriable наш код будет вести себя по разному.

A>>Блин, чем больше в лес, тем дальше вылез


ARK>Да, я про это как раз и говорю. Но, судя по дальнейшему обсуждению, монады таки не предполагают волшебного изменения кода...

Конкретная реализация, конкретного языка не предполагает. Возможно есть языки, которые предполагают.

СУВ, aikin
Re[51]: Есть ли вещи, которые вы прницпиально не понимаете...
От: akava Беларусь kavaleu.ru
Дата: 13.01.14 19:05
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Да, и выходит что самый оптимальный вариант получается в языке D, где мы можем переопределить все операторы для данного типа в одной функции. Если при этом ещё и все используемые функции являются шаблонными, то мы получаем полностью автоматическую замену T на optional<T> путём написания ровно одной функции и без модификации кода вообще.

Можно ссылку на это плиз?

СУВ, akava
Re[49]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 13.01.14 19:10
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>По факту, в C# код Синклера никак не поменяется. Потому что ECMA 334:14.2.7 Lifted Operators

S>В теории, хочется того же самого для пользовательских типов, а не только для Nullable<T>, оборудованного Compiler Magic.

Хы, ну для начала это очередная "встроенная монада" — такое нет смысла обсуждать в нашем контексте. Но что самое интересное, эта самая реализация "как бы лифтинга" как раз совсем не похожа на классическую, а гораздо больше напоминает обычную перегрузку операторов. ))) Т.е. я конечно не в курсе конкретной реализации, но есть подозрение, что там при реализации этих операторов, компилятор не вызывает каждый раз какую-то специальную функцию типа Nullable, а сам напрямую форвардит вызовы в T. Если это так, то это уже точно становится не явная монада, а просто некая отдалённо похожая концепция. Типа как исключения и т.п. — это вроде как тоже нечто напоминающее монады.
Re[37]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 13.01.14 19:22
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Я так понял, что речь идет не просто о чистых функциях, а о "выборочно чистых", к примеру чистых от работы с диском, но не от сетевых взаимодействий. В принципе, интересная идея, но в чем реальный бенефит выборочной чистоты и не будет ли это выглядеть адски страшно на любом ЯП — мне пока не ясно.


Хы, такими темпами можно дойти до введения "прав доступа" внутри языка. )))

Кстати, ООП со своей инкапсуляцией частично пытается решать эту проблему, причём с другой стороны. Не по принципу "проверим что эта функция не лезет куда не надо", а по принципу "код, который лезет куда не надо, нельзя вызвать ниоткуда, кроме спец. предусмотренных мест".
Re[51]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 13.01.14 19:40
Оценка:
Здравствуйте, akava, Вы писали:

A>Все реализуется на ассемблере. Вопрос в количестве телодвижений. Какой объем работы нужно проделать, чтобы реализовать все эти операции для optional<>, future<>, ...?


На D будет ровно по одной функции на каждый тип монад.

В C++ надо будет переопределить каждый оператор (сколько у нас их там?), но это можно сделать для шаблонного типа монад (т.е. в реализации вызывать некую функцию монады). Т.е. в итоге получаем по одной функции на каждый тип оператора и отдельно по одной функции для каждого типа монад.

В C# фокус из C++ не пройдёт и придётся определять заново все операторы для каждого типа монад.

Ну а в Хаскеле подобное вообще не сделать.

A>Ты, наверное, имеешь ввиду расставить руками в Хаскеле. Так?


Скорее просто про существующие языки. Ну во всяком случае общеизвестные. )))

A>Но дело в том, что Монада -- математическая конструкция. Которая никак не привязана к Хаскелю и другим реализациям.

A>И ничего нам не помешает реализовать специальный язык Монаскель, в котором вручную ничего расставлять не придется, но мы огребем вохрох проблем
Автор: akava
Дата: 13.01.14
(и это только те, что вижу я).


Не вижу особого смысла в создание подобного. )

A>Но даже сейчас, в Хаскеле, с помощью do-сахара нам, насколько я понял, не придется расставлять вызовы руками.


Эмм, так придётся расставлять собственно этот do-сахар. ))) Т.е. единственное его преимущество перед расстановкой просто bind в том, что он ставится сразу на некий блок кода (работающий с одними значениями), а не каждый вызов каждой функций/оператора в bind засовывать.
Re[52]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 13.01.14 19:52
Оценка:
Здравствуйте, akava, Вы писали:

A>Можно ссылку на это плиз?


Вот http://dlang.org/operatoroverloading.html

Кстати, я тут подумал... Теоретически на D можно сделать даже и автоматические вызовы нешаблонных функций f(T) с типом optional<T>. Там же есть перегрузка операции opDispatch и плюс функция mixin... Т.е. грубо говоря, мы можем тривиально написать код (одну функцию!), который придаст нашему классу optional бесконечное число функций-членов, каждый из которых просто вызывает глобальную функцию с тем же именем, передавая ей внутреннее значение optional.

Мда, всё же в C++ ещё очень много чего надо добавить, чтобы добиться возможностей D. И как видно, на области метапрограммирования надо концентрироваться в первую очередь, т.к. она позволяет делать потом вообще что угодно.
Re[53]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 14.01.14 01:15
Оценка: 18 (2)
Здравствуйте, alex_public, Вы писали:

_>Кстати, я тут подумал... Теоретически на D можно сделать даже и автоматические вызовы нешаблонных функций f(T) с типом optional<T>. Там же есть перегрузка операции opDispatch и плюс функция mixin... Т.е. грубо говоря, мы можем тривиально написать код (одну функцию!), который придаст нашему классу optional бесконечное число функций-членов, каждый из которых просто вызывает глобальную функцию с тем же именем, передавая ей внутреннее значение optional.


Накидал тут быстренько работающий пример:
double LibFunc(int v) {return 10.0*v;}

struct Optional(T){
    this(const T v) {this.v=v; ok=true;}
    string toString() {return ok?to!string(v):"nothing";}//для красоты примера, а вообще не требуется
    auto opBinary(string op, T2)(Optional!T2 t) {mixin Prepare!("v"~op~"t.v"); return ok&&t.ok?R(f()):R();}
    auto opDispatch(string name)() {mixin Prepare!("v."~name~"()"); return ok?R(f()):R();}
private:
    mixin template Prepare(string s) {const auto f=()=>mixin(s); alias Optional!(typeof(f())) R;};
    bool ok=false;
    T v;
};

auto Test(T)(T t1, T t2){return t1*t2+(t1+t2).LibFunc();}

writeln(Test(10, 20));
writeln(Test(Optional!int(10), Optional!int(20)));
writeln(Test(Optional!int(10), Optional!int()));

Данный код, как и полагается, выводит
500
500
nothing

и естественно все эти игры происходят исключительно во время компиляции и в итоге вырезаются оптимизатором.

Да, всё же D очень хорош, C++ заметно слабее. Ну а C# или Хаскель вообще даже рядом не валялись. )))
Re[50]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.14 03:15
Оценка:
Здравствуйте, alex_public, Вы писали:
_>Хы, ну для начала это очередная "встроенная монада" — такое нет смысла обсуждать в нашем контексте.
Не вижу причин не обсуждать. Вы спрашивали "зачем нужны монады" — я вам показываю примеры, зачем нужны монады.
Волшебным образом оказывается, что монады и недомонады встречаются в "обычных языках" и библиотеках на каждом углу.

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

Совершенно верно. Это compiler magic.

_>Если это так, то это уже точно становится не явная монада, а просто некая отдалённо похожая концепция. Типа как исключения и т.п. — это вроде как тоже нечто напоминающее монады.

Совершенно верно. Просто монады предлагают способ прикручивать поддержку исключений, Nullable, async, и прочего без compiler magic.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[48]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.14 05:45
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Эээ, что что? ) Насколько я понимаю, "главный" язык для работы с монадами у нас Хаскель. Так вот в нём компилятор не делает ничего подобного, а надо записывать всё руками.

Жаль.
_>Ну для начала, если мы говорим о C++, то скажем все наши функции реализованные в виде шаблонов заработают сами автоматом. )))
Осталось придумать, как реализовать в виде шаблонов функции типа возведения в степень. Желательно так, чтобы они работали и для комплексных чисел тоже.

_>Ну а нешаблонные действительно надо оборачивать в Apply. Так же как и в Хаскеле (только там в bind). И кстати в Хаскеле это единственный вариант, в отличие от C++.

Как я понял, всё же в Хаскеле есть какие-то синтаксические улучшения для монад.

_>Ээээ что что? ) Это в каком языке компилятор так умеет? )

В ограниченном виде query comprehensions в C# делают именно это.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[38]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.14 06:53
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Хы, такими темпами можно дойти до введения "прав доступа" внутри языка. )))


_>Кстати, ООП со своей инкапсуляцией частично пытается решать эту проблему, причём с другой стороны. Не по принципу "проверим что эта функция не лезет куда не надо", а по принципу "код, который лезет куда не надо, нельзя вызвать ниоткуда, кроме спец. предусмотренных мест".

Совершенно верно. Логичным продолжением ограничений является "... ниоткуда, кроме спец. предусмотренных мест, в которые лазить нужно специальным способом".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[49]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Evgeny.Panasyuk Россия  
Дата: 14.01.14 06:59
Оценка: 3 (1)
Здравствуйте, Sinclair, Вы писали:

_>>Ну для начала, если мы говорим о C++, то скажем все наши функции реализованные в виде шаблонов заработают сами автоматом. )))

S>Осталось придумать, как реализовать в виде шаблонов функции типа возведения в степень. Желательно так, чтобы они работали и для комплексных чисел тоже.

Уже есть в SGI STL: <b>std::power</b>. Работает и для целых, и для вещественных, и для комплексных, и даже для матриц.

Power is generalized exponentiation: it raises the value x to the power n, where n is a non-negative integer.


_>>Ну а нешаблонные действительно надо оборачивать в Apply. Так же как и в Хаскеле (только там в bind). И кстати в Хаскеле это единственный вариант, в отличие от C++.

S>Как я понял, всё же в Хаскеле есть какие-то синтаксические улучшения для монад.

Минимальные. Без синтаксических улучшений:
foo a b = a >>= \x ->
          b >>= \y ->
          return x + y
с do-сахаром:
foo a b = do x <- a
             y <- b
             return x + y
Re[50]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.14 09:19
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Уже есть в SGI STL: <b>std::power</b>. Работает и для целых, и для вещественных, и для комплексных, и даже для матриц.

Не вижу, каким образом оно работает для перечисленного:
EP>

EP>Power is generalized exponentiation: it raises the value x to the power n, where n is a non-negative integer.

Важное выделено. Даже в банальную вещественную степень возвести эта штука не сможет.

EP>Минимальные. Без синтаксических улучшений:

EP>
EP>foo a b = a >>= \x ->
EP>          b >>= \y ->
EP>          return x + y
EP>
с do-сахаром:

EP>
EP>foo a b = do x <- a
EP>             y <- b
EP>             return x + y
EP>

Интересно. А при этом с "обычными", немонадными a и b такая запись работает? Ну, то есть можно ли вообще всегда описывать функции в do-нотации, чтобы они работали с произвольными монадами?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[49]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.14 09:29
Оценка:
Здравствуйте, akava, Вы писали:

A>Еще один косяк с операциями, возвращающими bool. Например сравнение.


A>
A>if (m > limit) 
A>    Alert();
A>if (!(m <= limit)) 
A>    Alert();    
A>

A>Что тут делать? Если мы определим '>' над optional<> как false, в случае когда o == null, то первая инструкция будет игнорировать null, а вторая сообщать о них.
Да, для bool операций в шарпе лифтинг сделан особенным образом.

A>Т.е. нужно будет об этом задумываться. А если нужно будет задумываться, то когда-нибудь, какой-нибудь разработчик Леша заменит первый вариант на второй (или наоборот) и изменит семантику кода. Вот это тоже КОСЯК.

Я бы заставил лифтед-операции возвращать bool?, который несовместим с "обычным" if-ом. Тогда компилятор мне все такие места сразу сообщит, и заставит руками выписать реакцию на unknown.
Это не так удобно, как в шарпе, зато единообразно — потому, что lifted operator > (IEnumerable<T> left, IEnumerable<T> right) должен вовращать таки IEnumerable<bool>, а не одиночный bool.

A>Товарищи опытные "монадоведы", расскажите плиз, что в таких случаях делать? Сразу хочется работать с монадоми вручную, без компилятора, но тогда монады теряют весь смысл. Единственное, что я смог придумать это принцип: если нужно значение из монады, то получай его явно (т.е. вручную).

Зависит от монады. Если оператор преобразования в базовый тип — implicit, то и хрен бы с ним. А в случаях типа optional или list или ещё чего всё должно быть строго explicit.




ARK>>Ну хз, может я слишком перестраховываюсь, ведь эти рассуждения справедливы и в других случаях (Int32 заменили на Int64, например).

A>Я сам ХЗ. Не нужно воспринимать мои коментарии как "эгегей, монады куль, почему никто не использует монады...". Я сам только к ним присматриваюсь (как к новой для меня концепции).
A>Аргументы выше, это то, что я сам себе ответил, когда задался таким вопросом.


A>СУВ, akava
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[36]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Klapaucius  
Дата: 14.01.14 10:02
Оценка:
Здравствуйте, alex_public, Вы писали:

K>>Ну так надо делать не "шаблоны", а нормальный параметрический полиморфизм.

_>Чего чего? ) Это в смысле в рантайме?

Не понятно, что вы имеете в виду под "параметрическим полиморфизмом в рантайме" (я дискутировал с носителями самых фантастических представлений на этот счет, так что не провентилировав этот вопрос лучше даже и не начинать обсуждение).

_>Речь шла не про плюсы, а про гипотетический язык с шаблонами, в котором компилятор их полностью проверяет.


В гипотетическом языке можно сделать обязательные концепты и все будет типизировано, при том, что никакой "большой и лишней работы" тайпчекеру делать не придется.

_>Правильно, исходник по которому генерируется код. И только он, а не некие абстрактные исходники.


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

_>Я не собираюсь повторяться в третий раз. Даже дважды уже было много. Тем более, что в ответ не услышал даже одного раза.


Два раза много, а ноль раз, как в обсуждаемом случае — недостаточно. Повторяться не нужно — ответте на мои вопросы один раз. Этого будет достаточно.

_>Да да, конечно же совсем не признаёте... http://www.rsdn.ru/forum/philosophy/5407470
Автор: Klapaucius
Дата: 23.12.13
)))


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

Я не согласен, что это выглядит намного страшнее, чем в других языках (если не считать упомянутые мной "карательные" наименования, которые легко исправить). Монадический код часто, но не всегда, требует синтаксической обвязки для "стыковки" в отличие от функций вида a -> b в хаскеле, и потому код с мутабельными ссылками/массивами может выглядеть многословнее, чем хаскель-код с иммутабельными. Но в большинстве языков обычно наворочено столько синтаксического мусора без всякого смысла вообще, что на этом фоне и монадический хаскель-код выглядит вполне пристойно. Потому и вопрос — что это за язык такой, по сравнению с которым хаскельный код выглядит намного страшнее.


Т.е. раз у хаскеля нерастраченный на всякую ерунду синтаксический бюджет — какие-то редкие уродства погоды не делают, особенно если сравнивать с языком, сыплющим всюду синтаксический мусор лопатой. Поскольку С++ как раз такой, код на нем даже в тех областях, где он силен смотрится страшнее, чем хаскель-код, демонстрирующий самые неприглядные стороны хаскеля.
Гипотетическую возможность сделать синтаксис лучше, чем в хаскеле я, разумеется, не отрицаю.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[44]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 14.01.14 10:22
Оценка:
Здравствуйте, alex_public, Вы писали:

I>>Чего ты хочешь объяснить, я уже не понимаю. Большей частью у тебя сравнение query comprehension С# vs императивный код на С++.


_>Вообще всё началось с того, что я попросил знатоков (в том смысле, что применяющих их где-то на практике) монад показать какие-нибудь примеры их полезного использования в мультипарадигменных языках, а не в Хаскеле (в котором без

монад просто тоскливо).

Спирит открой и удивляйся. Я как то не слежу за бустом и С++, а то бы раньше показал этот пример.

_>Насколько я помню, практические единственным реальным примером были как раз твои реактивные монадные парсеры. Из плюсов надо отметить, что это действительно работающий пример. Ну а из минусов (что мы тут и обсуждали) — как мы увидели, тоже самое можно реализовать и без монад, причём частенько и ещё проще. Так что это хотя и был реальный ответ на мой вопрос, но он не стал аргументом в пользу монад.


Promise/Future ты забыл ?
Re[51]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Klapaucius  
Дата: 14.01.14 11:35
Оценка: 68 (1)
Здравствуйте, Sinclair, Вы писали:

S>Интересно. А при этом с "обычными", немонадными a и b такая запись работает? Ну, то есть можно ли вообще всегда описывать функции в do-нотации, чтобы они работали с произвольными монадами?


Чтоб такой код работал с обычными значениями, их придется обернуть в монаду Identity:

-- код был с ошибкой, правильно его записать так:

foo a b = do x <- a
             y <- b
             return $ x + y

-- или, что то же самое, но идиоматичнее:

foo = liftM2 (+)

-- теперь
runIdentity $ foo (Identity 2) (Identity 40)
-- получаем:
42

Это вполне применяется на практике, к примеру, все операции в пакете vector (это хаскельная библиотека для работы с массивами) монадические, а специализированная, нелифтнутые версии реализуются через монадические, вроде:

map f = mapM (return . f)


Lifted operators в хаскеле вполне реализуются:

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}

import Control.Applicative

instance (Applicative f, Num n) => Num (f n) where
    (+) = liftA2 (+)
    (-) = liftA2 (-)
    (*) = liftA2 (*)
    abs = fmap abs
    signum = fmap signum
    fromInteger = pure . fromIntegral

instance (Applicative f, Fractional n) => Fractional (f n) where
    (/) = liftA2 (/)
    recip = fmap recip
    fromRational = pure . fromRational

Все, теперь у нас арифметика лифтнута в любой аппликативный функтор и мы можем писать на языке j:

>>> 2 + 7 * 8
58
>>> Just 2 + Just 7 * Just 8
Just 58
>>> Just 2 + Nothing * Just 8
Nothing
>>> [1..3] + [7..9] * [11,12]
[78,85,89,97,100,109,79,86,90,98,101,110,80,87,91,99,102,111]
>>> getZipList $ ZipList[1..3] + ZipList[7..9] * ZipList[11..13]
[78,98,120]
-- функции - это тоже функторы и монады:
>>> sum / (fromIntegral . length) $ [1..3] -- вычисляем среднее значение: делим сумму на длину
2.0


Вообще, нормальная работа с функторами/монадами в хаскеле возможна, в основном, не благодаря спецсинтаксису (который как раз страшноватый), а благодаря приличным возможностям для написания полиморфного кода и комбинирования комбинаторов
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[63]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Evgeny.Panasyuk Россия  
Дата: 14.01.14 12:53
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>>>Вообще спирит, судя по доке, построен на комбинаторах парсеров. Отсюда совершенно не ясно, как он может являться аргументом против монад, если сам он именно монаду и представляет.

EP>>Комбинация парсеров — это не обязательно монада. Это может быть например аппликативным функтором (суперкласс монад, т.е. более общая структура).
EP>>Чтобы называть монадой, нужно как минимум найти нетривиальный bind.
I>Это ничего не меняет

В каком смысле? Ты хочешь называть Spirit монадой, но при этом не можешь показать где там bind (по смыслу)?
Re[51]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 14.01.14 13:00
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Совершенно верно. Просто монады предлагают способ прикручивать поддержку исключений, Nullable, async, и прочего без compiler magic.


Конечно. Только вот в современных мультипарадигменных языках это всё (и ещё очень много чего) уже есть, причём как раз с полной магией. Т.е. мой вопрос насчёт полезности монад в таких языках по прежнему остаётся в силе...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.