LINUX.ORG.RU

Сценарии использования алгебраических типов на практике

 ,


2

7

Для чего вы наиболее часто применяете алгебраические типы? С т.з. плюсовика, я в целом понимаю, что они делают, но не вижу, как бы их полезно применять. Допустим, если бы алгебраические типы были в С++ (полагаю что-то подобное можно на шаблонах сделать), для чего бы их использовать, с учётом того, что существует плюсовое ООП и если встроенное в язык ООП позволяет довольно лёгко решить задачу, то с помощью такого ООП и лучше её решать.

★★★★★

Последнее исправление: next_time (всего исправлений: 1)

Ответ на: комментарий от Deleted

В смысле, это не хорошо, но просто из практики, это обычное дело.

next_time ★★★★★
() автор топика

На той же Scala алгебраические типы данных используются повсеместно. Правда, судя по собеседованиям, не все пишущие на Scala понимают это, что скорее говорит об относительной популярности Scala, раз уж такое дело пошло

dave ★★★★★
()

С т.з. плюсовика, я в целом понимаю, что они делают, но не вижу, как бы их полезно применять.

Потому что это математика. Сборник больных сверхценных идей прямиком из средневековья. К практике вся эта чушь не имеет никакого отношения.

anonymous
()

алгебраические типы

наиболее общий составной тип, представляющий собой тип-сумму из типов-произведений

Ну охренеть. И что бы это значило. Нихрена не понял.
Видимо это тред для любителей лямбдо-монад:)
Ты бы хоть разжевал для плюсовиков что за зверь такой и чем интересен. Вряд ли тут много теоретиков.

MimisGotAPlan
()
Ответ на: комментарий от MimisGotAPlan

Ты бы хоть разжевал для плюсовиков что за зверь такой и чем интересен.

Представь. Средние века. Потомки вельмож, которые уже давно оторваны от какого-либо призводства. Земля на черепахах. Бублики, растущие на деревьях. И повсюду летающие ангелы, способные поместиться на острие иглы.

С какого хера эти уроды должны были что-то знать о программировании?

anonymous
()

Например когда парсер пишешь, алгебраические типы данных очень удобны в качестве узлов AST.

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

Например когда парсер пишешь, алгебраические типы данных очень удобны в качестве узлов AST.

Парсер Хаскелля на Хаскелле.

anonymous
()

Кроме того это довольно удобно в различных стейт-машинах. Ну и Some(..)/None безопаснее чем нулевые указатели.

Aswed ★★★★★
()

Похоже, нужно рассмотреть простенький пример с типичным использованием ADT.

Примером может быть простой калькулятор: класс (тип), который реальзует несколько методов: parse (принимает строку, возвращает некое представление ast), eval (принимает ast выражения и окружение: значения переменных и ast встроенных функций), simplify (принимает ast, применяет простые преобразования типа constant fold и похожих) и print (принимает ast, возвращает строку, которую передав в parse можем получить тот же ast).

anonymous
()
Ответ на: комментарий от next_time

Я имею ввиду, когда просматриваешь построенное дерево, паттерн матчинг безопаснее и нагляднее чем череда if-ов.

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

нагляднее чем череда if-ов.

так их не будет, будет вызов виртуальных функций

next_time ★★★★★
() автор топика

Вот смотри код на сях:

Rust 1.18 (комментарий)

А вот код с алебраическими типами.

https://play.rust-lang.org/?gist=78552afbc94610b245f5df2c32317c41&version...

Разве ты будешь делать наследование в таком примере?

А dynamic dispatch настолько медленный что в компиляторах даже есть оптимизации которые преобразовывают его обратно в switch. (devirtualization)

pftBest ★★★★
()
Ответ на: комментарий от pftBest

А dynamic dispatch настолько медленный

очень малый оверхед, по сравнению с вызовом по указателю на функции

обратно в switch.

только не обратно, в стандарте про виртуальные таблицы ничего нет

next_time ★★★★★
() автор топика
Ответ на: комментарий от pftBest

Разве ты будешь делать наследование в таком примере?

в том примере обыкновенный свитч можно использовать

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

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

pftBest ★★★★
()
Ответ на: комментарий от pftBest

Но обыкновенный свитч тебе не позволит так удобно распечатать содежимое структуры

с чего бы?

Плюс он менее устойчив к опечаткам и прочим ошибкам.

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

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

с чего бы?

Потому что компилятор не знает какое значение Tag соответствует какому полю в union, и поэтому не может автоматически сгенерировать код для распечатки (или сериализации в json или еще много чего) такого типа данных.

Эту информацию знает только программист и он должен держать ее в голове при работе с таким типом. Это к вопросу об устойчивости:

switch (data.Type) {
    case INT32:
        print(data.i64); // упс, перепутали поле
}

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

pftBest ★★★★
()
Ответ на: комментарий от next_time

в плюсоподобном ООП (С++, жаба, шарп) пишется много подготовительного мусора типа общий предок, куча классов, виртуальные ф-ции в каждый,

но зато в прикладном коде уже видно просто x->calc(y), условно говоря

я не понял, что из этого преимущество, а что - цена, которую за него нужно заплатить

MyTrooName ★★★★★
()
Ответ на: комментарий от next_time

а с другой стороны, непонятно, где бы это можно было бы с толком применить

Работу с шаблонами превращает из функциональщины в более понятную процедурщину, как с уже упомянутым c++17 if constexpr.

anonymous
()
Ответ на: комментарий от MyTrooName

преимущество в том, что простыня из свитч-кейсов по типу там или нет, превращается в вызов x->calc(y) в прикладном коде

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

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

преимущество в том, что простыня из свитч-кейсов по типу там или нет, превращается в вызов x->calc(y) в прикладном коде

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

читабельность бесполезного «прикладного» кода (x->calc(y)), конечно, выше. вот только вся бизнес-логика размазывается по N методам, и N декларациям классов в иерархии. иногда это хорошо, иногда нет.

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

В жаба-стайл это считается идеальным подходом.

next_time ★★★★★
() автор топика
Ответ на: комментарий от MyTrooName

читабельность
прикладной код
бизнес-логика
Избранные теги: coursera, desura, dwarf fortress, freelance, haskell, humble, humble bundle, humble indie bundle, kerbal space program, lorchess, minecraft, odesk, procrastination, python, python3, steam, upwork, прокрастинация

А вот и математики подтянулись.

anonymous
()
Ответ на: комментарий от next_time

тоже вроде классная штука, но непонятно зачем оно может быть нужно

Чтобы писать Хаскелль на Хаскелле. А еще оконный менеджер.

anonymous
()
Ответ на: комментарий от next_time

Да и ваще обычный enum в Си++ может быть примером простейшего алгебраического типа данных. Видишь, ты даже, скорее всего, ими постоянно пользуешься, а задаешь здесь такие забавные вопросы))

dave ★★★★★
()
Ответ на: комментарий от MyTrooName

ты python забыл вырезать

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

anonymous
()
Ответ на: комментарий от MyTrooName

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

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

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

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

anonymous
()
Ответ на: комментарий от MyTrooName

Бред нескладен по определению. Вот математическая писанина — это чистейший бред.

Очередной математик выстрелил себе в ногу.

anonymous
()
Ответ на: комментарий от anonymous

Бред нескладен по определению

если бы бред был нескладен, в него бы никто не верил

Вот математическая писанина — это чистейший бред

вчера было тоньше

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

если бы бред был нескладен, в него бы никто не верил

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

anonymous
()

Применение std::optional:

  • ленивая инициализация поля класса
  • отложенная инициализация — мы пишем конструктор и видим, что конструктор поля хочет аргументов, но во всём конструкторе объекта или хотя бы в списке полей инициализации аргументов для конструирования поля пока ещё нет, optional и метод emplace решают проблему
  • возврат из функции опционального результата - например, после открытия диалога выбора файла файл может быть выбран или не выбран, если пользователь нажал «отмена»; аналогично при чтении следующей строки из файла её может просто не быть

Применение std::variant:

  • вернуть корни квадратного уравнения (их может не быть, можеть быть 1 корень, может быть 2 корня и может быть ошибка «уравнение не является квадратным»)
  • хранить значение из JSON (которое может быть булевым, строкой, числом либо рекурсивной структурой данных, т.е. объектом или массивом)
  • хранить значение переменной в интерпретаторе языка с динамической типизацией
  • замена комбинации enum и switch: в switch можно забыть обработать одно из значений, либо после мержа двух веток появится код, обрабатывающий не все значения enum; при необработанных случаях variant будет ошибка компиляции
  • variant подойдёт везде, где нужен enum с прикреплёнными данными (например, к типу подписки/лицензии можно сразу прикрепить данные о подписке/лицензии)

Если на выходе либо результат, либо ошибка, то optional не подходит, т.к. не хранит информацию об ошибке. А variant подойдёт.

Я также использовал variant для хранения кода ошибки вместо enum, причина описана выше в пункте про switch.

quiet_readonly ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.