Re[35]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 06.01.14 15:25
Оценка:
Здравствуйте, Ikemefula, Вы писали:

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


И в чём проблема возникнет в случае промисов? )
Re[30]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.01.14 16:35
Оценка:
Здравствуйте, alex_public, Вы писали:

I>>Будет тоже самое, только вместо >>= будет функция


_>Ну функция вместо оператора это не принципиально... Так покажешь компилируемую реализацию liftM2 на C#? )


C# в отличие от С++, не умеет rank-2 полиморфизм, в ём хилый вывод типа. Это, в кратце, означает, что лифтинг придется писать для каждого типа монад или эмулировать этот rank.2.

так
(mt1, mt2) => from x in mt1 
              from y in mt2 
              select f(x, y);


должен быть определен метод SelectMany для монадического типа

или так
     (mt1,mt2) => mt1.Bind(t1 => mt2.Bind(t2 => MonadicType.Unit(f(t1, t2))));


должны быть определены методы Bind и Unit для монадического типа

Скажем, в джаваскрипте rank2 полиморфизм можно сэмулировать:

function liftM2(monadic, f)
{
     return (mt1,mt2) => monadic.bind(mt1, t1 => monadic.bind(mt2, t2 => monadic.unit(f(t1, t2))));
}


Нужен тупо самый минимум — bind и unit. Т.е. полиморфизм в JS гораздо лучше, чем в C#

I>>Ога, ты читать пробовал то самое сообщение, где пример кода был ?


_>Пример кода (если ты про C#) мне как бы ни к чему, т.к. нет никакого желания лазить по документации Rxx и понимать его смысл. Мне нужен тестовый набор входных и выходных данных и всё. Что бы после реализации никто уже точно не придрался к коду (выдаёт нужное — значит правильный).


Все что надо уже дадено

_>Эммм, так никто и не собирается искать решение в виде "одного мега регулярного выражения". Решение задачи даёт императивный код (который, как ты понимаешь, может в принципе всё, вопрос только какой ценой в смысле размера кода). Просто его размер резко сокращается, если использовать в нём регулярные выражения.


А если использовать реактивную модель в декларативном виде, то размер кода еще сильнее сокращается.

Все очень просто — этот декларативный код есть не что иное, как дсл в который упрятаны все императивные кишки которые у тебя торчат направо и налево
Re[54]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.01.14 16:43
Оценка:
Здравствуйте, alex_public, Вы писали:

_>А можно сделать практически БНФ без всяких монад и в не функциональных языках.


Так покажи уже эту пульку, сделай на ней реактивный парсер, а то одни слова.

I>>Меня интересует практическая ценность. Попробуй вывести на экран свою скорость и расскажи, как ты сможешь это использовать.


_>Ты что-то совсем плаваешь в теме похоже. Скорость — это первая производная от функции и в принципе определена в точке. И её величина как раз и должна скакать как угодно. Ещё имеем среднюю скорость (думаю можно не уточнять что это такое?) на интервале — её значение существенно зависит от величины интервала и естественно более сглажено.


Мгновенная скорость никого не интересует, вообще. Когда говорят просто скорость, имеют ввиду все что угодно но не мгновенную скорость. И эта скорость имеет значение только на некотором временном интервале.

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

_>Касательно конкретно твоей задачки. Определись просто что тебе надо выводить на экран. Скорость или же усреднённую на каком-то интервале скорость.


Есть просто скорость и есть мгновенная скорость, которая никого не интересует.

>И кстати во втором случае в нормальном софте обычно позволяют регулировать размер интервала и при этом в зависимости от этого параметра значение средней скорости вполне может и знак поменять даже...


Правильно и это легко делается — меняется размер интервала.

_>А вообще это всё не имеет никакого отношения к данной темке. Но это ты зачем-то увёл разговор сюда. Хотя я не против — мне тема численных вычислений вполне близка. )))


Это имеет непосредтсвенное отношение — наглядно демонстрирует свойства твоего решения.
Re[34]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.01.14 17:03
Оценка:
Здравствуйте, alex_public, Вы писали:

_>В C# есть по крайне мере перегрузка операторов и простенький вариант обобщённых типов. Этого уже достаточно, чтобы сделать приличное задание подобных шаблонов в коде. Но народ похоже просто увлечён той кривой хренью, которая например лично мне даже и для коллекций не нравится. Иного объяснения не нахожу.


Перегрузка операторов и обобщенные типы очень слабые, это специально сделано. До кучи очень слабый вывод типа, что, в итоге, дает очень слабый полиморфизм — на всё надо писать методы, подсказки и тд и тд.

I>>За десять минут уложишься ?


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


Да при чем здесь переписывание спирита, я про код конкретной задачи. Представь, что спирит уже переписали под реактивный парсинг или например есть реактивный парсер в императивном виде на С++ и тд.
Re[36]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.01.14 17:11
Оценка:
Здравствуйте, alex_public, Вы писали:

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


_>И в чём проблема возникнет в случае промисов? )


Вариантов решения ровно 2
1. лифтинг

     var result  = ComplexFunction(f, g, h, something.getX());


2. водопроводный код, т.е. в самом простом случае, надо писать примерно так

     something.getX().then(x => ComplexFunction(f, g, h, x)).then(result => ....);
Re[3]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Evgeny.Panasyuk Россия  
Дата: 06.01.14 17:12
Оценка:
Здравствуйте, Кодт, Вы писали:

К>А моноиды и эндофункторы — это теоретический базис и гарантия того, что 0*X = X*0 = 0, 1*X = X*1 = 1, X*Y*Z = X*Y*Z (скобки расставьте по вкусу)


1. Нуля в общем случае нет.
2. В законе для нейтрального элемента очепятка — должно быть 1*X = X*1 = X
Re[5]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Evgeny.Panasyuk Россия  
Дата: 06.01.14 18:47
Оценка:
Здравствуйте, Кодт, Вы писали:

DM>>Вот мой вариант "монады за две минуты".

К><>
DM>>Мысль 2. Каждую строчку можно считать функцией, принимающей результат вычисления предыдущей (может его использовать, может не использовать), и производящей какой-то свой результат. Т.е. код выше можно переписать как
К><>
К>Это не "монады за 2 минуты", а "продолжения за 2 минуты".

Правильно — сходство ведь большое. Если развернуть do-сахар как раз и будет видна цепочка вложенных продолжений.
Основное отличие от CPS в том, что между действиями вводится дополнительный слой в виде custom'ного бинда, с определённой структурой (ассоциативность даёт интуитивность вложенных do, и т.п.).
Re[17]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Evgeny.Panasyuk Россия  
Дата: 06.01.14 19:46
Оценка:
Здравствуйте, Klapaucius, Вы писали:

_>>А чего конкретно в C++ не хватает для поддержки подобной функциональщины?

K>Да, собственно, всего. Там даже Upward Funarg Problem не решена.

Всё решено.

K>А это самый минимум, необходимый для того, чтоб вообще можно было о какой-то поддержке ФП говорить. Это даже в C# есть.


Сборщик мусора пытается управлять только памятью, да и то возможны утечки. Если же брать управление ресурсами в общем — то и C# и Haskell сливают C++.
Например попробуй сделать аналог:
auto foo()
{
    auto x = 5;
    ofstream f("log.txt");
    auto y = make_shared<Foo>(11);

    return [f=move(f), =](auto z)
    {
        f << z << endl;
        return x + y->data;
    };
}

int main()
{
    cout << foo()("OMG!");
}
Как только замыкание выходит из scope файл закрывается и Foo освобождается.
Re[29]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Evgeny.Panasyuk Россия  
Дата: 06.01.14 20:01
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Сравните:

K>
K>liftM2 :: Monad m => (a -> a1 -> b) -> m a -> m a1 -> m b
K>

K>и
K>
K>template<template<class>class M, typename R, typename T1, typename T2>
K>function<M<R>(M<T1>,M<T2>)> liftM2(R (*f)(T1, T2))
K>


K>Во втором случае (на псевдоплюсах) нигде не написано, что это за M. Использование >>= никак не отражено в сигнатуре. Вот про это я и говорил "нетипизировано" и "несодержательная сигнатура"


А что конкретно смущает? То что при плохом "M" произойдёт ошибка в теле шаблона? Так это решается, причём даже в рамках C++1998 — просто добавляется enable_if. Причём даже перегрузка будет работать (то есть можно сделать один liftM2 для монад, второй ещё для чего-нибудь).
Re[31]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Evgeny.Panasyuk Россия  
Дата: 06.01.14 20:18
Оценка:
Здравствуйте, Klapaucius, Вы писали:

_>>А насчёт нетипизированности... Обычно под этим подразумевают, что компилятор может пропустить ошибку и она всплывёт только где-нибудь во время исполнения. В данном случае, если в качестве M передать тип не имеющий определённого оператора >>=, то компилятор выдаст соответствующую ошибку — какую ещё типизацию то можно требовать?

K>Такую, чтоб ошибки возникали не при "передавании типа", а при написании обобщенного кода. Обобщенный код на плюсах практически нетипизированный, хотя нетипизированность в данном случае обычно называют "permissiveness", но сути это не меняет.

Late binding позволяет выводить типы там, где Haskell нужно заводить "с толкача"
Автор: Evgeny.Panasyuk
Дата: 15.08.13
.

K>Об этом я и писал: "На самом деле понятно, как это предполагается использовать обобщенно, но проблема тут будет в том, что это обобщение не типизировано. Родственная проблема — семантическая неопределенность. Про (=<<) можно много чего сказать не зная ничего о конкретной имплементации, про ваш перегруженный сдвиг ничего сказать нельзя."


К параметрам-типам шаблонов можно указывать как синтаксические требования (C++98 SFINAE, C++11 decltype SFINAE, C++14 Concepts), так и семантические — через traits (пользователь подписывается под тем, что его тип удовлетворяет необходимым аксиомам).
Re[29]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Evgeny.Panasyuk Россия  
Дата: 06.01.14 20:25
Оценка:
Здравствуйте, Ikemefula, Вы писали:

_>>Как я понимаю ты согласился, что у C++ гораздо больше возможностей для реализации функциональных фишек в стиле Хаскеля, чем у C#? )

I>На бумажке больше, а на практике без внятного GC для лямбд толку никакого, чемодан без ручки.

GC это полумера:
using System;
using System.IO;

public class Test
{
    public delegate void fireworks();
    public static fireworks make_closure(FileStream fs)
    {
        return () => fs.Read(new byte[10], 0, 10); // "чемодан без ручки"
    }
    public static fireworks fire()
    {
        using (var fs = File.Open("file", FileMode.Open))
        {
            return make_closure(fs);
        }
    }
    public static void Main()
    {
        fire()(); // System.ObjectDisposedException
    }
}
Re[29]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Кодт Россия  
Дата: 06.01.14 20:39
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Сравните:

K>
K>liftM2 :: Monad m => (a -> a1 -> b) -> m a -> m a1 -> m b
K>

K>и
K>
K>template<template<class>class M, typename R, typename T1, typename T2>
K>function<M<R>(M<T1>,M<T2>)> liftM2(R (*f)(T1, T2))
K>


K>Во втором случае (на псевдоплюсах) нигде не написано, что это за M. Использование >>= никак не отражено в сигнатуре. Вот про это я и говорил "нетипизировано" и "несодержательная сигнатура"


Ну понятно, что мета-типизация у плюсов утиная. Но компилятор всё равно проверит наличие функций из словаря Monad, — если они были востребованы, конечно. Так что эти утки крякают не в рантайме.
А при желании можно явно прикрутить контракт — "принадлежность M<*> к модели Monad", самым простым способом — через enable_if и т.п.
Просто для хаскелла это является не желанием, а требованием, которое смягчено автоматическим выводом сигнатуры.
Сравни
liftM2 f ma mb = do { a<-ma; b<-mb; return f a b }

здесь нигде не сказано Monad m =>, но do-нотация или водопровод на это намекают. Так же, как на это будет намекать водопровод в определении плюсовой функции liftM2.


_>>Суть в том, что на практике монады как раз нужны достаточно редко.

K>Т.е. возвращать из функций вида a -> m b и передавать в другие — это все-таки редко нужно, я правильно понял?

Мне здесь внезапно увиделась фиксация: раз в хаскелле эндофункторы — это из типа в тип и из функции в функцию, то давайте и во всех остальных языках будем проецировать типы и функции. При том, что механизмы операций над типами и функциями или убоги, или просто другие.
Не могу словами выразить, но чувствую, что где-то кидают.
Перекуём баги на фичи!
Re[30]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.01.14 21:03
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

_>>>Как я понимаю ты согласился, что у C++ гораздо больше возможностей для реализации функциональных фишек в стиле Хаскеля, чем у C#? )

I>>На бумажке больше, а на практике без внятного GC для лямбд толку никакого, чемодан без ручки.

EP>GC это полумера:

EP>
EP>


GC к твоему коду не имеет никакого отношения, а твой код не имеет никакого отношения к лифтингу. Так что ни о чем
Re[31]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Evgeny.Panasyuk Россия  
Дата: 06.01.14 21:08
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>>>На бумажке больше, а на практике без внятного GC для лямбд толку никакого, чемодан без ручки.

EP>>GC это полумера:
EP>>
EP>>

I>GC к твоему коду не имеет никакого отношения,

О чём и речь — лямбды есть, GC есть — а чемодан всё равно без ручки
Re[32]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.01.14 21:24
Оценка: -1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

I>>GC к твоему коду не имеет никакого отношения,


EP>О чём и речь — лямбды есть, GC есть — а чемодан всё равно без ручки


Для лямбд в C# есть всё что надо, нет rank-2 полиморфизма для монад, решается метапрограммированием довольно легко. Ручки нет, но можно приделать.

В С++ есть rank-2, но лямбы без ручки и приделать её нельзя, только руками-руками-руками.
Re[3]: Есть ли вещи, которые вы прницпиально не понимаете...
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 07.01.14 00:08
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK>vim имеет удобно интегрированную поддержку регулярных выражений, что позволяет легко и быстро производить такую обработку текста.


MSVS, что характерно, тоже умеет по регексам искать. А в Productivity Power Tools есть еще куча мелочей на эту темы.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[31]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 07.01.14 02:17
Оценка: +1
Здравствуйте, Ikemefula, Вы писали:

I>или так

I>     (mt1,mt2) => mt1.Bind(t1 => mt2.Bind(t2 => MonadicType.Unit(f(t1, t2))));

I>должны быть определены методы Bind и Unit для монадического типа

Собственно это нормальный вариант и эти функции по любому определяются и в Хаскеле и в том моём примере. Только вот как ты и сам сказал, тебе придётся писать по отдельной реализации liftM2 для каждого типа монады, что уже совсем не дело.

Кстати, Klapaucius говорил как раз о чём-то подобном, когда намекал что у C++ могут быть какие-то сложности с реализацией liftM2. Похоже что его знания императивных языков ограничиваются как раз такими как C# и Java. )))

I>А если использовать реактивную модель в декларативном виде, то размер кода еще сильнее сокращается.


I>Все очень просто — этот декларативный код есть не что иное, как дсл в который упрятаны все императивные кишки которые у тебя торчат направо и налево


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

Если же сравнивать именно такие вещи, то надо взять с одной стороны эту твою библиотеку, а с другой скажем реактивный вариант boost.spirit и сравнить какой объём кода получается у них...

Кстати, тебе наверное должны нравиться вот такие https://github.com/beark/ftl/blob/master/docs/Parsec-I.md штуки... А мне это всё как-то совсем не нравится.
Re[55]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 07.01.14 02:24
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Так покажи уже эту пульку, сделай на ней реактивный парсер, а то одни слова.


Я же не сказал, что подобная библиотека существует. Хотя написать её никаких принципиальных проблем нет. Просто определённый объём работы.

I>Мгновенная скорость никого не интересует, вообще. Когда говорят просто скорость, имеют ввиду все что угодно но не мгновенную скорость. И эта скорость имеет значение только на некотором временном интервале.


Ужас какой. ))) Скорость — это первая производная. И точка, без всяких вариантов.

I>Правильно и это легко делается — меняется размер интервала.


Ну так если в твоей задачке надо выводить алерты по значению средней скорости на каком-то интервале, то прямо так и сказал бы. Это конечно же чуть сложнее, чем вариант с просто скоростью — не одна строчка кода, а целых две.
Re[35]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 07.01.14 05:31
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Да при чем здесь переписывание спирита, я про код конкретной задачи. Представь, что спирит уже переписали под реактивный парсинг или например есть реактивный парсер в императивном виде на С++ и тд.


Если ты про ту свою задачку анализатора логов, то я ещё раз говорю, что для неё скорее всего просто императивный код на регулярных выражениях проще будет. Реактивный естественно. Т.е. что-то вроде:
void Analyze(string s)
{
    static string js;
    match what;
    if(regex_match(s, what, "/*длинный шаблон фильтрующий js*/")) js+=what[1];
    if(regex_match(js, what, "startSync(.+)endSync(.*)")){
        string res=what[1];
        js=what[2];
        if(res.find("pir:")&&regex_match(res.remove("pir:"), what, "function ([^ (]+)")) res=what[1];
        cout<<res;
    }
}
Re[37]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 07.01.14 05:32
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Вариантов решения ровно 2


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