C++ lectures at MIPT (in Russian). Lecture 9a. Monads

Поділитися
Вставка
  • Опубліковано 17 лис 2024

КОМЕНТАРІ • 10

  • @DrUlrih
    @DrUlrih 2 роки тому +1

    В FORTRAN есть pure спецификатор 😃

  • @samolisov
    @samolisov 2 роки тому

    Не очень понятен такой момент, в первом примере со State, у нас >= возвращал обернутое в состояние значение, а > был finally - возвращал просто значение. В примере со списками же flatmap берет функцию, строящую из элемента список и применяет ее к списку, но в отличие от fmap, возвращает не список списков, а просто список. Чем не уже готовый finally? Почему finally это просто fmap, которой наоборот, если дать функцию из элемента списка в список и сам список, построит нечто обернутое - список списков, а не flatmap?

  • @yogthemuskrat
    @yogthemuskrat 4 роки тому +1

    А грядущий consteval не является аналогом атрибута [[pure]]? Ну или близким родственником.

    • @tilir
      @tilir  4 роки тому +2

      Не является. Consteval означает что функции вообще не будет на этапе исполнения. А pure означает чистое исполнение. Немного разные вещи

    • @yogthemuskrat
      @yogthemuskrat 4 роки тому

      @@tilir Понятно. Спасибо за пояснение.

  • @dimhazel
    @dimhazel 5 років тому +1

    Так почему ты переопределил операторы > и >=, а не операторы >> и >>=?

    • @tilir
      @tilir  5 років тому +2

      Никаких серьёзных обоснований тут нет. Можно взять любые.

    • @ivankorotkov2563
      @ivankorotkov2563 3 роки тому +2

      Обоснование может быть в том, что >>= правоассоциативна, поэтому если ее перегружать, то придется раставлять скобочки:
      ((wrap_state(make_pair(0, 0)) >>= nfoo) >>= nbar) >> buz;

  • @oficsu
    @oficsu 4 роки тому +3

    Что касается аттрибута pure... Идея замечательная, но я считаю, что это ни в коем случае не должен быть аттрибут. Будет некрасиво, если аттрибут будет менять наблюдаемое поведение программы. А этот аттрибут либо будет, поскольку побочные эффекты вполне наблюдаемы, либо будет крайне ограничен. Если мы не хотим менять наблюдаемое поведение - компилятору придётся в случае отсутствия тела пессимистично предполагать, что функция не чистая, чтобы не испортить корректность кода
    Вероятно это должен быть оператор + спецификатор, являющийся частью типа функции. Тогда, во-первых, мы сможем обязать компилятор проверять, что функция действительно чистая, а во-вторых, мы сможем делать идеальные врапперы, которые будут повторять чистоту функций
    29:44. Раз уж никто не предоставил в комментариях реализацию flatten - буду первым:
    template
    auto concat(LIST1 l1, LIST2 l2) {
    return l1([l2](auto... l1xs){
    return l2([l1xs...](auto... l2xs){
    return List(l1xs..., l2xs...);
    });
    });
    };
    template
    auto concat(LIST1 l1, LIST2 l2, REST... rest) {
    return concat(concat(l1, l2), rest...);
    };
    auto flatten = [](auto f, auto... xs) {
    return concat(List(), List(), f(xs)...);
    };
    Но решение определённо занимает больше 4 строк. Применив н̶е̶м̶н̶о̶г̶о̶ ̶м̶а̶г̶и̶и̶ fold expressions и C++20, можно заметно сократить пример:
    // godbolt.org/z/9b8z1a
    auto operator+(auto list1, auto list2) {
    return list1([list2](auto... l1xs){
    return list2([l1xs...](auto... l2xs){
    return List(l1xs..., l2xs...);
    });
    });
    };
    auto flatten = [](auto f, auto... xs) {
    return (f(xs) + ...);
    };
    Ну... тела действительно теперь в сумме занимают 4 строчки, но... То ли требовалось от решения или здесь есть более лаконичная альтернатива?
    И да, несмотря на то, что это самая короткая лекция на канале, и я имею при этом небольшое знакомство с ФП, это была, всё же, самая длинная лекция, спасибо)
    UPD: а̶ ̶д̶а̶в̶а̶й̶т̶е̶ ̶п̶о̶с̶о̶р̶е̶в̶н̶у̶е̶м̶с̶я̶ ̶в̶ ̶о̶б̶ф̶у̶с̶к̶а̶ц̶и̶и̶ ̶к̶о̶д̶а̶ ̶б̶л̶а̶г̶о̶д̶а̶р̶я̶ ̶р̶е̶к̶у̶р̶с̶и̶в̶н̶ы̶м̶ ̶л̶я̶м̶б̶д̶а̶м̶?
    constexpr auto flatten = [](auto func, auto x1, auto x2, auto... rest) {
    if constexpr (sizeof...(rest)) return operator()(func, operator()(func, func(x1), x2), rest...);
    else return x1([func, x2](auto... l1xs){
    return func(x2)([l1xs...](auto... l2xs){ return List(l1xs..., l2xs...); });
    });
    };
    Этот код работает в GCC и MSVC, Clang же не допускает использование operator() в теле лямбды ( godbolt.org/z/4rK5ra ), думаю, здесь стоит поискать ответ в стандарте, кто же прав

    • @oficsu
      @oficsu 3 роки тому +2

      Поскольку UA-cam выдал shadow ban на мой же ответ под этим сообщением, я, спустя 4 месяца, и во второй раз просто его скопирую, удалив ссылку на стандарт (не позволяет даже часть ссылки оставить) и наше C++ сообщество в Телеграм, где дали эти пояснения:
      Кажется, Clang прав:
      The lambda-expression's compound-statement yields the function-body ([dcl.fct.def]) of the function call operator, but for purposes of name lookup, determining the type and value of this and transforming id-expressions referring to non-static class members into class member access expressions using (*this) ([class.mfct.non-static]), t͟h͟e͟ ͟c͟o͟m͟p͟o͟u͟n͟d͟-͟s͟t͟a͟t͟e͟m͟e͟n͟t͟ ͟i͟s͟ ͟c͟o͟n͟s͟i͟d͟e͟r͟e͟d͟ ͟i͟n͟ ͟t͟h͟e͟ ͟c͟o͟n͟t͟e͟x͟t͟ ͟o͟f͟ ͟t͟h͟e͟ ͟l͟a͟m͟b͟d͟a͟-͟e͟x͟p͟r͟e͟s͟s͟i͟o͟n
      А in the context of the lambda-expression нам недоступен operator(), однако, это могло бы быть очень приятным синтаксическим сахаром