Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Ikemefula, Вы писали:
I>>Ты просто не хочешь увидеть, ибо аргументы у тебя навроде "я всё это могу на с++ тупо императивно".
_>Для начала давай разделять "можно на C++" и "можно императивно". Это разные вещи. Чаще всего я как раз показываю, что предложенное решение можно без проблем реализовать и в C++ прямо в оригинальном (не императивном) виде.
Ого, в оригинальном не императивном ? Это наверное на другом форуме, все твои решения здесь это обычный императивный код на С++.
>Однако потом обычно говорю, что это всё нафиг не нужный мусор, разведённый ради мифической красоты (а в реальности для программистских "понтов") и тупой императивный код в лоб решает задачу быстрее. Причём быстрее и по итоговому коду и по времени его написания.
Я и вижу — ты уже в который раз дал решение не той задачи или не тот код
_>И кстати говоря далеко не все вещи из других языков реально повторить на C++. Например некоторые возможности реализуемые в D на C++ повторить не реально. Хотя с обычно обсуждаемым с тобой языком такого конечно быть не может, там всё наоборот. Кстати, как раз в тему... Как по твоему, реально ли написать на C# функцию liftM2 подходящую для произвольного типа монад? На Хаскеле очевидно легко. На C++ тоже без проблем, как я показал здесь http://www.rsdn.ru/forum/philosophy/5417607
Я честно говоря не понимаю, что такое liftM2
I>>Пример что я привел никакой не гипотетический. _>Только он вообще не имеет никакого отношения к эффектам, на которые намекает Klapaucius...
Наоборот.
I>>Ты решил не ту задачу У меня разбор некоторого контекстно-свободного языка реактивным парсером.
_>Тут прямо в точности оно и есть. Мой код вызываем для каждой приходящей строки и получаем тот же результат, что и у тебя. )
Нет, не получаем.
Re[48]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
I>>Но переделывать то надо ? А мне даже отдельной функции заводить не надо
_>Эээээ, это ты типа сейчас сравниваешь процесс использования некой готовой библиотеки и с процессом написания кода альтернативной библиотеки? ))) Оригинальненько... )))
Я говорю про вычислительную модель а ты пытаешься общий случай заменить частным, показывая примеры императивного кода.
Тебе нужно прекратить стёб и показать саму вычислительную модель, она у тебя императивная, которая покроет все возможные кейсы
I>>Не получается по одной строчке на каждое условие
_>НУ это у кого как. )))
I>>Это _не_ скорость, а просто дельта текущего и предыдущего значений.
_>Дааа? )
Да. Пудозреваю, ты и ускорение можешь вычислить точно так же — дельтой текущего и предыдущего значений.
>Т.е. у тебя замеры анализируемого значения производятся не через равные промежутки времени и в нашу функцию анализа передаётся ещё и массив значений этих интервалов? ) Потому как в противном случае дельта — это и будет скорость. )))
В моем случае вообще не важно, через какие промежутки времени производятся замеры. Нужна скорость — это с помощью 1 функции получаем новый эвент стрим который будет скорость показывать. Еще один стрим — ускорение. Всё. Эта функция естественно, будет накапливать интервалы за некоторую единицу времени Y.
I>>Это тянет на нобелевку. Пример — на регулярных выражениях правильно вырезать определенные теги, которые, внезапно, могут быть вложенными.
_>Вообще то подразумевалось, что регулярное выражение используется для нахождения момента с которого мы будем пропускать данные
Это ты сам себе упростил. Вот простая задача — одинаковые вложеные теги заменяем одним, если некоторый интересующий контент есть только в самом низу. т.е.
<a><a></a><a><a>ф</a></a></a> = <a>ф</a>
<a x="a"><a></a><a><a>ф</a></a></a> = <a>ф</a>
>(у нас же потоковая обработка вроде как), а не для самого вырезания из всего объёма данных... Однако если бы мы вдруг захотели именно подобное вырезание, то оно тоже вполне реально, в том числе и для вложенных тэгов.
ля-ля-ля. покажи регэксп для случая выше. Ты в который раз уже хочешь свести контекстно-свободную грамматику к регулярной и мне это порядком надоело. Толи ты не понимаешь, что пишешь, то ли ты специально дурака валяешь.
Re[28]: Есть ли вещи, которые вы прницпиально не понимаете...
Во втором случае (на псевдоплюсах) нигде не написано, что это за M. Использование >>= никак не отражено в сигнатуре. Вот про это я и говорил "нетипизировано" и "несодержательная сигнатура"
_>Писать то можно... Только кто это делает? )
Все делают. В том же Rx множество комбинаторов, для которых никакого спецсинтаксиса нет.
_>Почему я вижу определение грамматики через select, where и т.п.? )
Отлично, мы вернулись на несколько постов назад. Мне скопипастить свой ответ или сами прочитаете?
_>Суть в том, что на практике монады как раз нужны достаточно редко.
Т.е. возвращать из функций вида a -> m 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[22]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Да, правильно, код внутри монад будет доступен из окружающего его кода в том же самом красивом режиме. Но что если у нас практически весь код приложения находится в монадах? )
Вы так и не объяснили, что вы имеете в виду, говоря "код внутри монад".
_>Тогда в общем то эти плюсы пропадают в никуда.
Какие плюсы? И куда они пропадают?
_>А когда я говорил о заметно меньшем удобстве, то подразумевался процесс написания кода внутри монад. Причём он на мой взгляд хуже и обычного хаскеля и императивных аналогов...
Конечно не хуже, потому что если бы он был хуже императивных аналогов, вы давно бы уже привели код и можно было предметно обсудить недостатки.
Но раз вы не приводите примеры "как в хаскеле" и "как на плюсах" и даже "как должно быть" — значит, очевидно, вы считаете, что ваш тезис примеры не подтвердят. Поэтому остается только повторять одно и то же о "меньшем удобстве" и "худшем коде", ничего конкретно не говоря.
_>В этом примере ещё не всё так страшно, т.к. некая часть программы занята логикой, которая выражается "нормальным" хаскелем. В реальном системном ПО или же тех же примеров из самого wxHaskell соотношение такого кода гораздо хуже.
О да! У игры "астероиды" такая могучая "логика", куда там "реальному системному ПО".
_>Но даже здесь хорошо видна разница между этими областями в приложение.
Это не всем хорошо видно. Не могли бы вы в этом коде обозначить, какие области "кошерные", а какие печальнее C++?
_>Ну а если мы сравним этот пример с его аналогом на C++, то будет всё совсем печально.
Похоже, с сайтом проблемы: хаскель-код у меня отображается, а "аналог на C++" — нет, так что сравнить не получается.
'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[28]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Писать то можно... Только кто это делает? ) Почему я вижу определение грамматики через select, where и т.п.? )
Потому что лично мне понравился вот такой пример. Ты определись, чего хочешь — обсуждать монады или обсуждать лично мои примеры или обсуждать фичи языка который понравился лично мне — C#.
Грамматика на C# через linq сделана потому, что в C# паттерн матчинга нет, но можно сэмулировать частные случаи через query comprehension.
Вопрос — какое отношение имеет паттерн матчинг конкретного языка к монадам ?
Пудозреваю, тебя сейчас порвёт: "Я, Я, Я знаю — это можно сделать на регэкспах !!!111расрас".
K>>Суть как раз в этом. Если у вас exp возвращает double, то принимая числа даже меньше 1000 он уже возвращает ерунду. Просто система обработки ерунды встроена в операции с плавучкой. Понятно, что для большинства типов такой автоматической обработки нет и ее нужно организовывать. Кроме того, я сразу написал, что монады нужны для комбинирования функций вида a -> m b, и там же написал что полезно для комбинирования функций других видов. Мне теперь это повторять в каждом предложении?
_>Суть в том, что на практике монады как раз нужны достаточно редко. А их частое использование в Хаскеле всего лишь следствие некоторых неудобностей языка (которые являются ценой за некоторые особенности, возможно приносящие плюсы, а возможно и нет — это мы так и не выяснили пока).
На практике монады нужны всегда. Ты с коллекциями работаешь ? А это монада, встроеная в язык/фремворк. С исключениями работаешь ? А это монада, встроеная в язык/фремворк.
Re[44]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали: _>Естественно, потому как при использование for'a вынесение кода в отдельную функцию не приносит никакой пользы. Но мне почему-то казалось, что на данном форуме ни у кого не может быть проблем с мысленным преобразованием такого кода _>в такой _>
_>Ну если кому-то это сложно, то сорри... )
Вот как раз мне — несложно. А вот вам пока заниматься преобразованиями в уме рано. Кто вам сказал, что одновременно идёт итерация только по одной коллекции? И это я ещё не имею в виду многопоточный случай. Вариант нашего коллеги, в отличие от вашего, хранит состояние локально. _>Этот тоже работающий — я другой не показываю. )))
Простите, но уже вторая попытка не удалась. И это мы рассматриваем примитивнейший случай, где автомату не нужен даже магазин.
В мало-мальски интересном реальном случае у вас рука устанет пот утирать при "мысленном преобразовании кода". Я же вам уже намекал — компиляторы придумали не потому, что человек неспособен раскладывать переменные по регистрам и стеку, а потому, что компьютер это делать не устаёт.
_>1. Ну так вообще то как раз я и показывал вариант, в котором всё разделено. Имеем функцию Analyze. Её можно вызвать хоть из цикла (активно), хоть как реакцию на сообщения (реактивно).
Пока что нельзя.
_> Далее, в самой функции мы можем и написать ручной код (в простых случаях), и вставить мощный конечный автомат на базе какой-то библиотеки, и вставить вообще готовое решения для анализа данных на базе какого-то удобного синтаксиса задания грамматики. Вот это действительно раздельная архитектура, обеспечивающая гибкость и удобство.
Вы пример попробуйте привести. В большинстве известных мне случаев текст функции Analyze без поллитры читать совершенно невозможно. Характерный пример — оконная функция на заре виндов, когда не было бесчисленных Фреймворков, и весь её код состоял из огромного switch, да ещё и с вложениями.
Восстановить логику приложения по этой простыне — совершенно нереально, даже в несложных случаях.
_>А как раз Rx на фоне этого выглядит монолитной хренью заточенной только под один узкий вариант.
Под какой именно вариант?
_>2. Если говорить конкретно о процессе анализа, то идея записывать "грамматику" через sql операторы — это на мой взгляд полная дикость.
Вам же уже написали, что использовать синтаксис query comprehension, как и везде в linq, не обязательно. Можно писать в любимом императином стиле, как в вашей функции Analyze — только без граблей глобальных переменных.
_>Несколько сомнительная идея. Потому как непонятно о чём должны сигнализировать сообщения парсера. Если о приходе узлов, то как бы всё равно получится что придёт только одно сообщение на документ, причём опять же только после прихода всего документа.
Это если весь XML состоит исключительно из одного корневого узла. А если там есть хоть какая-то структура, то сообщения будут приходить сразу после завершения каждого узла.
Да, это означает некоторый риск нарваться на non-welformedness или invalidity документа уже в процессе анализа. Но в интересующих нас случаях это всё ещё лучше, чем ждать всего документа.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Ого, в оригинальном не императивном ? Это наверное на другом форуме, все твои решения здесь это обычный императивный код на С++.
В данной темке естественно, т.к. вроде как ни у кого не возникает сомнений (хотя вот у Klapaucius возникли сомнения насчёт liftM2, но я их рассеял), что реализовать монады на C++ легко. Так что тут уже остаётся для дискуссии только вопрос о пользе их применения.
I>Я честно говоря не понимаю, что такое liftM2
Это функция, которая берёт на входе функцию вида C f(A, B), а возвращает функцию вида M<C> f(M<A>, M<B>), где M — это некий монадный тип. Т.е. грубо говоря liftM2 переделывает обычную функцию, в функцию работающую со значениями упакованными в монадный тип. Одна из стандартных вещей в Хаскеле, как и просто liftM, Которая по сути fmap.
Как, такое по силам написать на C#? )
_>>Только он вообще не имеет никакого отношения к эффектам, на которые намекает Klapaucius... I>Наоборот.
Дааа? ) Т.е. ты хочешь сказать, что Rx приносит в C# особенности IO/ST Хаскеля (это которые кстати существует в том числе и совсем без монад)?
I>Нет, не получаем.
Ну давай набор тестовых данных (входные строки и ожидаемый текст на выходе) — посмотрим. )))
Re[28]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Sinclair, Вы писали:
S>>Суть в том, что если у вас нету монад, то при желании уметь отложенное вычисление sin и exp вам придётся писать отдельную функцию exp(Promise<double>) и sin(Promise<double>). S>>А с монадами у вас есть универсальный способ написать только double-версию sin() и exp(), и бесплатно получить sin(exp(List<double>), sin(exp(Promise<double>)), sin(exp(Promise<List<double>>)) и так далее.
_>Вообще то это у нас описание функторов, а не монад.
Что именно вы называете "функтором"? Функциии типа List<double> exp(List<double> a)? Так речь не о них, а о List<double> с некоторыми доп. плюшками. _>Но даже если бы это были монады... Какой смысл в протягивание этой дополнительной сущности между sin(exp()), когда можно это сделать по "краям"? )
"этой" — это какой? Что такое "протягивание"? И что значит "по краям"? Вы имеете в виду, что можно сразу работать с функцией sinexp == sin(exp())?
Ну это же ещё лучше — вы предлагаете писать рукопашный код не только для каждого сочетания монад, но и для каждой комбинации функций. На всякий случай намекну, что помимо функций одного аргумента есть ещё и функции нескольких аргументов. Имея скалярную функцию Multiply(a, b) я при помоши монад автоматически получаю векторную функцию Multiply(double a, List<double> l) и прочие варианты.
И всё это — всего лишь за счёт того, что монада определяет три "штуки": композиция, декомпозиция, и применение. В традиционных ООП языках система типов недостаточно выразительна, чтобы описать монаду явно. А в ФП-языках для монад есть встроенная поддержка.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[49]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Я говорю про вычислительную модель а ты пытаешься общий случай заменить частным, показывая примеры императивного кода.
I>Тебе нужно прекратить стёб и показать саму вычислительную модель, она у тебя императивная, которая покроет все возможные кейсы
Что-то ты уже сам себя запутал. Давай ка я кратко повторю свои тезисы, а ты скажешь с чем несогласен.
И так, Rxx позволяет нам производить анализ так называемых push-коллекций с помощью некого монадного парсера, заданного через linq синтаксис.
1. push-коллекции — никогда не имел ничего против этой полезной разновидности паттерна Наблюдатель. Единственно что, авторы библиотеки естественно должны предусмотреть ещё и удобное использование того же кода активным образом. Не знаю как с этим в Rx, но надеюсь, что там всё же не идиоты делали. )))
2. монадный парсер... Ну в принципе рабочий вариант конечно, но в данном случае мне кажется что использование именно монад является всего лишь следствием пункта 3. Т.е. на самом деле тут можно было сделать намного удобнее, например использовав перегрузку операторов и соответственно задавая грамматику полноценными выражениями (создавая такой мини DSL). Однако тогда бы не вышел пункт 3 — поэтому выбрали не самый удобный монадный вариант.
3. linq синтаксис: задание грамматики через sql операторы — это на мой взгляд полный бред и дикость.
I>Да. Пудозреваю, ты и ускорение можешь вычислить точно так же — дельтой текущего и предыдущего значений.
Ну естественно что ускорение — это дельта текущего и предыдущего значения скорости (при равных промежутках времени). А по твоему не так что ли? )))
I>В моем случае вообще не важно, через какие промежутки времени производятся замеры. Нужна скорость — это с помощью 1 функции получаем новый эвент стрим который будет скорость показывать. Еще один стрим — ускорение. Всё. Эта функция естественно, будет накапливать интервалы за некоторую единицу времени Y.
Т.е. тебе для такой тривиальной вещи необходимо плодить новый поток сообщений? Ужас какой...
I>Это ты сам себе упростил. Вот простая задача — одинаковые вложеные теги заменяем одним, если некоторый интересующий контент есть только в самом низу. т.е. I><a><a></a><a><a>ф</a></a></a> = <a>ф</a> I><a x="a"><a></a><a><a>ф</a></a></a> = <a>ф</a>
Ты вот постоянно криво ставишь условия задачи) А потом, когда видишь её решение, начинаешь на ходу менять. Вот наверняка и тут будет тоже самое. Ну да ладно, давай последний раз попробуем. ))) Для конкретно этого условия проблему решит выражение: (<a[^>]*>(<a[^>]*></a>)*)+ф((<a[^>]*></a>)*</a>)+
Re[29]: Есть ли вещи, которые вы прницпиально не понимаете...
K>Во втором случае (на псевдоплюсах) нигде не написано, что это за M. Использование >>= никак не отражено в сигнатуре. Вот про это я и говорил "нетипизировано" и "несодержательная сигнатура"
Почему это на "псевдоплюсах"? )))
А насчёт нетипизированности... Обычно под этим подразумевают, что компилятор может пропустить ошибку и она всплывёт только где-нибудь во время исполнения. В данном случае, если в качестве M передать тип не имеющий определённого оператора >>=, то компилятор выдаст соответствующую ошибку — какую ещё типизацию то можно требовать?
И кстати говоря это полностью укладывается в классическую идеология шаблонов C++, работающую на базе SFINAE.
K>Т.е. возвращать из функций вида a -> m b и передавать в другие — это все-таки редко нужно, я правильно понял?
Да, цепочки вида m a->m b->m c возникают весьма редко. И в этих редких случаях монады как раз оправданы (в любых языках).
K>Ну так назовите хоть одну. Что это за "неудобности" такие, которые вынуждают в хаскеле монады использовать, и которых в другом языке нет и использовать монады ничто не вынуждает. K>Вы раз за разом повторяете, что они есть, но назвать ни одной не можете.
Мы же вроде как это уже обсудили один раз. Это особенности реализации IO/ST в Хаскеле. Правда вы указали, что эти особенности привносят некие плюсы по сравнению с другими языками. Подразумевая, что эти плюсы (которых в других языках в принципе нет) перевешивают все ужасы подобного кода. Однако, моя просьба привести хотя бы один пример, демонстрирующий суть этих плюсов на практике, была полностью проигнорирована...
Re[23]: Есть ли вещи, которые вы прницпиально не понимаете...
Вообще то я ещё в самом первом сообщение на данную тему (про wxHaskell) точно указал что и где надо сравнивать. Если вы так до сих пор этого не увидели, то мне если честно надоело повторяться.
Re[29]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Потому что лично мне понравился вот такой пример. Ты определись, чего хочешь — обсуждать монады или обсуждать лично мои примеры или обсуждать фичи языка который понравился лично мне — C#.
Вообще то это не просто твой пример, а пример с заглавной страницы библиотечки Rxx, так что он очень даже характерен...
I>Грамматика на C# через linq сделана потому, что в C# паттерн матчинга нет, но можно сэмулировать частные случаи через query comprehension.
I>Вопрос — какое отношение имеет паттерн матчинг конкретного языка к монадам ?
Потому как задавать грамматику можно гораздо более удобными способами. И в таком случае монады становятся не нужны (в данном конкретном случае естественно, а не вообще в жизни).
I>Определение грамматики можно сделать и без query comprehension — http://rsdn.ru/forum/philosophy/5416669.1
I>Пудозреваю, тебя сейчас порвёт: "Я, Я, Я знаю — это можно сделать на регэкспах !!!111расрас".
Не, это как раз случай где максимально рулит Boost.Spirit с его удобным (именно для таких целей) DSL'ем.
I>На практике монады нужны всегда. Ты с коллекциями работаешь ? А это монада, встроеная в язык/фремворк. С исключениями работаешь ? А это монада, встроеная в язык/фремворк.
Так вообще то именно об этом и шла основная ветка данной дискуссии. Насколько нужны монады (в явном виде) в мультипарадигменных языках, в которых вся основная подобная функциональность уже встроенная и нет ограничений типа чистых функций Хаскеля и т.п.
Re[45]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Sinclair, Вы писали:
S>Вот как раз мне — несложно. А вот вам пока заниматься преобразованиями в уме рано. Кто вам сказал, что одновременно идёт итерация только по одной коллекции? И это я ещё не имею в виду многопоточный случай. Вариант нашего коллеги, в отличие от вашего, хранит состояние локально.
Оу, когда начинают цепляться к оформлению тестовых примеров (кстати Ikemefula это уже делал — можно было бы почитать хотя бы мой ответ ему), то это означает что по делу сказать уже вообще нечего...
S>Это если весь XML состоит исключительно из одного корневого узла. А если там есть хоть какая-то структура, то сообщения будут приходить сразу после завершения каждого узла. S>Да, это означает некоторый риск нарваться на non-welformedness или invalidity документа уже в процессе анализа. Но в интересующих нас случаях это всё ещё лучше, чем ждать всего документа.
Да, такое можно сделать, но тогда опять же непонятно зачем нам именно такие данные. Они же будут приходить в очень странной последовательности, по отношению к оригинальной структуре. Например для <a></a><b><c><c/></b> придёт как a, c, b. И зачем нам оно такое?
Re[29]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Sinclair, Вы писали:
S>Что именно вы называете "функтором"? Функциии типа List<double> exp(List<double> a)? Так речь не о них, а о List<double> с некоторыми доп. плюшками.
Применение функций вида A f(B) к скажем List<B> (и получая List<A>) — это у нас просто функтор, а не монада. Монада у нас появится, если мы имеем дело с функцией вида List<A> f(B) и пытаемся применить её к List<B>.
S>"этой" — это какой? Что такое "протягивание"? И что значит "по краям"? Вы имеете в виду, что можно сразу работать с функцией sinexp == sin(exp())? S>Ну это же ещё лучше — вы предлагаете писать рукопашный код не только для каждого сочетания монад, но и для каждой комбинации функций. На всякий случай намекну, что помимо функций одного аргумента есть ещё и функции нескольких аргументов.
И в чём проблема то? ) Покажите на конкретном примере, а то что-то не видно из общих слов.
S>Имея скалярную функцию Multiply(a, b) я при помоши монад автоматически получаю векторную функцию Multiply(double a, List<double> l) и прочие варианты.
Это всё опять же просто функторы, разновидности на тему fmap.
S>И всё это — всего лишь за счёт того, что монада определяет три "штуки": композиция, декомпозиция, и применение. В традиционных ООП языках система типов недостаточно выразительна, чтобы описать монаду явно. А в ФП-языках для монад есть встроенная поддержка.
Да без проблем всё это записывается и в нормальных ООП языках. Можно прямо в этой темке глянуть примеры. Вопрос только в том нафига оно вообще нужно в большинстве случаев.
Re[30]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Вообще то это не просто твой пример, а пример с заглавной страницы библиотечки Rxx, так что он очень даже характерен...
Пример мой потому что я его привел. Он достаточно простой что бы можно было понять основные вещи.
I>>Вопрос — какое отношение имеет паттерн матчинг конкретного языка к монадам ?
_>Потому как задавать грамматику можно гораздо более удобными способами. И в таком случае монады становятся не нужны (в данном конкретном случае естественно, а не вообще в жизни).
Удобство это субъетивно. Вот наверняка в форуме С++ найдется ктото, кому тупой recursive descent на сотни килобайт окажется удобнее чем 1000 строк грамматики.
I>>Определение грамматики можно сделать и без query comprehension — http://rsdn.ru/forum/philosophy/5416669.1
I>>Пудозреваю, тебя сейчас порвёт: "Я, Я, Я знаю — это можно сделать на регэкспах !!!111расрас".
_>Не, это как раз случай где максимально рулит Boost.Spirit с его удобным (именно для таких целей) DSL'ем.
Снова феерическая чушь — я показал пример _реактивного_ парсинга ! буст.спирит такой парсинг не умеет, как все твои yacc и lexx.
Если считаешь иначе — покажи, наконец, пример этого самого _реактивного_ парсинга, грамматику возьми из моего примера про формат чисел с плавающей запятой.
В принципе хрен с ним, со спиритом, сделай хотя бы императивно, но что бы это был честный реактивный код, условимся, для простоты, что в эвентах инфа приходит по одному символу. Скажем я могу запускать такие парсеры хоть асинхронно в одном потоке, хоть в разных, могу менять, добавлять комбинаторы как угодно. А у тебя чуть что, так надо подкладывать костыли, например из за многопоточности, паралеллизма и тд и тд и тд.
Вот и покажи, как получить эту гибкость императивным подходом.
I>>На практике монады нужны всегда. Ты с коллекциями работаешь ? А это монада, встроеная в язык/фремворк. С исключениями работаешь ? А это монада, встроеная в язык/фремворк.
_>Так вообще то именно об этом и шла основная ветка данной дискуссии. Насколько нужны монады (в явном виде) в мультипарадигменных языках, в которых вся основная подобная функциональность уже встроенная и нет ограничений типа чистых функций Хаскеля и т.п.
Речь шла об этом, но ты как раз сказал, что монады не нужны.
Чистые функции хаскеля это не ограничение. Ограничение это шаблоны С++, когда ты >>= и =<< не можешь вынести в тип.
Отсюда в Хаскеле много меньше ограничений, чем в С++, с т.з. высокоуровневых конструкций. Вот в низкоуровневом коде там, наоборот, больше ограничений. Например сортировка на хаскеле никогда не получится быстрее чем на С++. А вот разные хитрые алгоритмы поведения персонажей в игре ты вспотеешь выписывать на С++. Собтсвенно игры давно ушли от с++ в этой части.
Re[50]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Что-то ты уже сам себя запутал. Давай ка я кратко повторю свои тезисы, а ты скажешь с чем несогласен.
_>И так, Rxx позволяет нам производить анализ так называемых push-коллекций с помощью некого монадного парсера, заданного через linq синтаксис.
Нет. Парсер можно задавать комбинаторами безо всякого Linq. Забудь вообще про Linq, linq нужен для паттерн матчинга.
_>1. push-коллекции — никогда не имел ничего против этой полезной разновидности паттерна Наблюдатель. Единственно что, авторы библиотеки естественно должны предусмотреть ещё и удобное использование того же кода активным образом. Не знаю как с этим в Rx, но надеюсь, что там всё же не идиоты делали. )))
Что значит удобно, кому удобно, тебе мне или тому, кто кроме циклов и ветвлений ничего в глаза не видел ?
_>2. монадный парсер... Ну в принципе рабочий вариант конечно, но в данном случае мне кажется что использование именно монад является всего лишь следствием пункта 3. Т.е. на самом деле тут можно было сделать намного удобнее, например использовав перегрузку операторов и соответственно задавая грамматику полноценными выражениями (создавая такой мини DSL). Однако тогда бы не вышел пункт 3 — поэтому выбрали не самый удобный монадный вариант.
С монадами получается гораздо лучший ДСЛ, именно потому, что скобочек, кавычек и разных лишних слов будет меньше, чем в твоем варианте на шаблонах.
_>3. linq синтаксис: задание грамматики через sql операторы — это на мой взгляд полный бред и дикость.
Мне кажется, ты до сих пор не понял, что грамматика задается не через linq, черз linq она обрабатывается, т.е. это эмуляция паттерн матчинга.
Мне что, объяснить, что эмуляция паттерн матчига будет хуже чем полноценный паттерн матчинг ?
I>>Да. Пудозреваю, ты и ускорение можешь вычислить точно так же — дельтой текущего и предыдущего значений.
_>Ну естественно что ускорение — это дельта текущего и предыдущего значения скорости (при равных промежутках времени). А по твоему не так что ли? )))
Нет, не так. В твоей модельке и скорость и ускорение меняются в зависимости от частоты опросов. Вот изменился уровень сигнала за одну минуту с 0 до 60, скорость изменения — 1 ед/c
С твоей "формулой" ты получишь 60 значений и например вполне возможно, последнее будет отрицательным. Опаньки — скорость отрицательная, а сигнал растёт.
I>>В моем случае вообще не важно, через какие промежутки времени производятся замеры. Нужна скорость — это с помощью 1 функции получаем новый эвент стрим который будет скорость показывать. Еще один стрим — ускорение. Всё. Эта функция естественно, будет накапливать интервалы за некоторую единицу времени Y.
_>Т.е. тебе для такой тривиальной вещи необходимо плодить новый поток сообщений? Ужас какой...
Моя модель гарантирует отображение скорости, а твоя при росте уровня сигнала может показывать отрицательную скорость.
I>>Это ты сам себе упростил. Вот простая задача — одинаковые вложеные теги заменяем одним, если некоторый интересующий контент есть только в самом низу. т.е. I>><a><a></a><a><a>ф</a></a></a> = <a>ф</a> I>><a x="a"><a></a><a><a>ф</a></a></a> = <a>ф</a>
_>Ты вот постоянно криво ставишь условия задачи)
Задачу привел Синклер, а я привел простейший пример( для SAX парсера XML).
>А потом, когда видишь её решение, начинаешь на ходу менять.
Ога. Это мы с Синклером сговорились, он придумал XML SAX, а я подобрал вариант который под это подходит.
>Вот наверняка и тут будет тоже самое. Ну да ладно, давай последний раз попробуем. ))) Для конкретно этого условия проблему решит выражение: (<a[^>]*>(<a[^>]*></a>)*)+ф((<a[^>]*></a>)*</a>)+
Ты снова частный случай выдал Что мне делать, если теги будут b ? А если в них будет какой то контент, который тоже надо скипнуть ?
Итого — ты в очередной раз попытался натянуть регулярную грамматику на контекстно свободный язык.
Re[26]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>В данной темке естественно, т.к. вроде как ни у кого не возникает сомнений (хотя вот у Klapaucius возникли сомнения насчёт liftM2, но я их рассеял), что реализовать монады на C++ легко. Так что тут уже остаётся для дискуссии только вопрос о пользе их применения.
I>>Я честно говоря не понимаю, что такое liftM2
_>Это функция, которая берёт на входе функцию вида C f(A, B), а возвращает функцию вида M<C> f(M<A>, M<B>), где M — это некий монадный тип. Т.е. грубо говоря liftM2 переделывает обычную функцию, в функцию работающую со значениями упакованными в монадный тип. Одна из стандартных вещей в Хаскеле, как и просто liftM, Которая по сути fmap. _>Как, такое по силам написать на C#? )
Конечно же нет, я ведь погулять вышел.
_>Дааа? ) Т.е. ты хочешь сказать, что Rx приносит в C# особенности IO/ST Хаскеля (это которые кстати существует в том числе и совсем без монад)?
Телепатируй дальше, не буду мешать.
I>>Нет, не получаем.
_>Ну давай набор тестовых данных (входные строки и ожидаемый текст на выходе) — посмотрим. )))
То есть, ты решил забрать свои слова на счет того, что не знаешь что такое optional, second и тд ?
optional(second('pir', jsFunction('takeName()'))
эта хрень парсит джаваскрипт, если перед ним идет pir и вырезает имя функции
Мне чисто любопытно, прежде чем перейдем к тестовым данным, ты и вправду считаешь, что готов хотя бы это покрыть регулярными выражениями ?
у меня будет работать даже вот так (+ мусор который стрипается)
s
t
a
r
t
S
y
n
c
p
i
r
f
u
n
c
t
i
o
n
n
a
m
e
(
)
{
}
e
n
d
S
y
n
c
а вообще, я поторопился, у меня в коде ошибка, блоки start-end не вложеные, а должны быть вложенными.
то есть надо вот так
var expr = empty();
var targetPattern = between(word('startSync'), expr, word('endSync'))
expr.overWrite(or(targetPattern, optional(second('pir', jsFunction('takeName()')))));
...
.takeWhen(targetPattern)
то есть, теперь будут найдены все имена функций во вложеных startSync endSync
Но я не сомневаюсь, что ты и здесь найдешь решение на регулярных выражениях
Re[30]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
K>>Т.е. возвращать из функций вида a -> m b и передавать в другие — это все-таки редко нужно, я правильно понял?
_>Да, цепочки вида m a->m b->m c возникают весьма редко. И в этих редких случаях монады как раз оправданы (в любых языках).
Частота зависит от программиста. Скажем если работа с асинхронщиной, то совершенно не ясно, почему это должно возникать редко Наоборот, очень часто — есть коллекция А, есть коллекция Б, их надо смержить. Но вот фокус, они приходят в промисах.
и получается вот такое
var result = merge(getA(),getB());
парадокс — по этому коду нельзя сказать, какой он, синхронный или асинхронный, если не смотреть использование или не глянуть внутрь. Есть один большой минус — брейкпоинты некуда статить.
P.S. Я уже знаю, что это называется "лифтинг".
Re[30]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
S>>И всё это — всего лишь за счёт того, что монада определяет три "штуки": композиция, декомпозиция, и применение. В традиционных ООП языках система типов недостаточно выразительна, чтобы описать монаду явно. А в ФП-языках для монад есть встроенная поддержка.
_>Да без проблем всё это записывается и в нормальных ООП языках. Можно прямо в этой темке глянуть примеры. Вопрос только в том нафига оно вообще нужно в большинстве случаев.
Не получается. Я наколбасил две небольшие библиотечки, вроде тех что в примерах кода видны, но шота пока не вижу ни одного примера, где бы это было более-менее удобоваримо.
На самом деле у тебя возражение про Rx совершенно справедливое, только ты проблему не там ищешь. Посмотри внимательно на Rx или Rxx и тебе станет понятно, что не может быть нормальных монад в обычном ООП языке, если они не встроены сразу в язык.
Re[31]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Пример мой потому что я его привел. Он достаточно простой что бы можно было понять основные вещи.
Я к тому, что запись грамматики через linq — это не твоё изобретение, а как раз авторов библиотеки. Т.е. это не твой неудачный пример, а подразумеваемая стандартная практика.
I>Снова феерическая чушь — я показал пример _реактивного_ парсинга ! буст.спирит такой парсинг не умеет, как все твои yacc и lexx.
Так речь шла о задание грамматики, а не об этом. Можно же без проблем написать парсер работающий реактивно и при этом с заданием грамматики в стиле boost.sprit. Вот для этой задачи такое и было бы оптимальным.
I>В принципе хрен с ним, со спиритом, сделай хотя бы императивно, но что бы это был честный реактивный код, условимся, для простоты, что в эвентах инфа приходит по одному символу. Скажем я могу запускать такие парсеры хоть асинхронно в одном потоке, хоть в разных, могу менять, добавлять комбинаторы как угодно. А у тебя чуть что, так надо подкладывать костыли, например из за многопоточности, паралеллизма и тд и тд и тд.
Ой, да хватит уже цепляться к тому тестовому примеру. Очевидно же, что если бы я писал библиотечный парсер, то это по любому был бы класс, который учитывал бы всё это и ещё кучу всяких нюансов типа обработки ошибок и т.п. Только никто в своём уме не будет писать такое ради выкладывание на форум.
I>Речь шла об этом, но ты как раз сказал, что монады не нужны.
Не совсем. Я сказал что они не нужны в большинстве случаев. Т.е. что есть редко встречающийся набор реальных задач, на которые монады идеально ложатся (типа различных конвейеров и т.п.). И естественно, что эти задачи надо решать через что-то типа монад в любых языках. Далее, в Хаскеле у нас монады вообще на каждом углу, но это из-за особенностей реализации там IO/ST и на мой взгляд скорее недостаток языка. А ещё, в некоторых других языках народ пытается протащить монады туда, где они реально не требуются...
I>Чистые функции хаскеля это не ограничение. Ограничение это шаблоны С++, когда ты >>= и =<< не можешь вынести в тип.
Сами чистые функции — это естественно не ограничение, а плюс. Они и в D есть например. Проблема то у Хаскеля совсем другие и всем прекрасно известны...