Size: a a a

2021 March 24

АГ

Александр Гранин... in ФП
Daniil Kostin
Я пытаюсь понять ФП.
Вроде все просто, но как сделать что-то свое не понятно.
Пытаюсь сделать механизм транзакций для функций.
У меня есть некая функция, которая возвращает результат и ждет завершения цепочки. Оборачиваем ее TransactionTask<ResultType>(someFn(TransactionTask<ResultType> it)) для ее запуска нужен общий completer.
Transaction инициализирует completer, принимает цепочку TransactionTask и по endTx() запускает стек.

Подскажите, с чего начать?
Вроде похоже на FreeMonad, но не совсем. Если често я никак не могу понять как из ФП объектов Монада, Функтор собрать то, что мне надо.
Что такое контекст тоже не совсем понятно. Iterable<A> Iterable - контекст, А конкретный тип объекта в этом контексте?

Есть код, но там пока одна монолитная сущность Transaction, она сама как TransactionTask. Но нужна еще вложенность. Поэтому планирую, что репозиторий будет оборачивать исполнени каждого своего метода в TransactionTask. TransactionTask<PostData> create(String post) => TransactionTask.pure((it) ...);

pastebin.pl/view/f68173d4
Ниже есть тесты как это работает
Привет! В точности то, что я уже делал (Software Transactional Memory). Да, Free monad, но не слишком простой:

https://github.com/graninas/cpp_stm_free

(Есть еще версия для Haskell)
источник

DK

Daniil Kostin in ФП
Александр Гранин
Привет! В точности то, что я уже делал (Software Transactional Memory). Да, Free monad, но не слишком простой:

https://github.com/graninas/cpp_stm_free

(Есть еще версия для Haskell)
О, спасибо, не ожиданно.
источник

АГ

Александр Гранин... in ФП
Daniil Kostin
Нужна некая сущность которая может вернуть результат и одновременно ждать "остальных" или команды того, кто ее исполняет. Иначе она сама занает как откатиться назад
stm::STML<stm::Unit> takeForks(const TForkPair& forks) {
   stm::STML<stm::Unit> lm = takeFork(forks.left);
   stm::STML<stm::Unit> rm = takeFork(forks.right);
   return stm::sequence(lm, rm);
}
Вот здесь функции takeFork "делают" что-то свое мутабельное с данными в виде транзакций, а потом объединяются в еще большую транзакцию. Слово "делают" не вполне верное, потому что тут декларация. Выполнение будет уже после.
источник

АГ

Александр Гранин... in ФП
Daniil Kostin
О, спасибо, не ожиданно.
У меня есть несколько материалов для прояснения темы:

- Туториал
https://gist.github.com/graninas/c7e0a603f3a22c7e85daa4599bf92525
- Доклад
https://www.youtube.com/watch?v=VHZPcz8HwZs
источник

АГ

Александр Гранин... in ФП
Для C# я тоже хотел сделать, но руки не дошли
источник

АГ

Александр Гранин... in ФП
Версия для Haskell:
https://github.com/graninas/stm-free

Примеры для C++ версии:
- https://github.com/graninas/stm_samples
- https://github.com/graninas/cpp_philosophers_stm

В общем, материалов много, спрашивайте, если что нужно
источник

АГ

Александр Гранин... in ФП
Daniil Kostin
Если хандл ожидания выдает исключение или false - что-то во всей цепочке пошло не так, то есть действие компенсируещее. Допустим йункция пишет что-то в файл и надо вернуть состояние обратно
Вот здесь есть проблема. Не всякое IO действие можно откатить. И общего алгоритма rollback не существует
источник

АГ

Александр Гранин... in ФП
Поэтому транзакционные модели предполагают только изменение данных, но не эффекты. Эффекты можно привязать к результату выполнения/невыполнения транзакции
источник

DK

Daniil Kostin in ФП
Александр Гранин
Вот здесь есть проблема. Не всякое IO действие можно откатить. И общего алгоритма rollback не существует
там условно, у меня реальные транзакции базы, которе надо объединить в UnitOfWork
Но нет механизмов как C#
источник

АГ

Александр Гранин... in ФП
Daniil Kostin
там условно, у меня реальные транзакции базы, которе надо объединить в UnitOfWork
Но нет механизмов как C#
Тогда, пожалуй, лучше подойдет другой мой подход, тоже Free monad based. Транзакции к БД, которые могут быть вложенными друг в друга. Но здесь есть только пример на Haskell
источник

АГ

Александр Гранин... in ФП
Есть фреймворк Hydra. В нем есть Free monad based язык SqlDB, на котором можно описывать несколько транзакционных запросов к БД и выполнять их как одну в рамках реальных транзакций:

https://github.com/graninas/Hydra/blob/60d591b1300528f5ffd93efa205012eebdd0286c/lib/hydra-free/src/Hydra/Core/Lang/Language.hs#L39

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

АГ

Александр Гранин... in ФП
@danleech У вас с Haskell как?
источник

АГ

Александр Гранин... in ФП
Может, мне лучше порекомендовать свою книгу? Там это описано
источник

DK

Daniil Kostin in ФП
Александр Гранин
Тогда, пожалуй, лучше подойдет другой мой подход, тоже Free monad based. Транзакции к БД, которые могут быть вложенными друг в друга. Но здесь есть только пример на Haskell
У меня основная проблема, что транзакция в моем окружении - функция с приватной зоной отлова ошибок. И мне надо внедрить управление внутрь каждой такой функции через транзакцию уже моей реализации. Или писать ORM свое.
источник

АГ

Александр Гранин... in ФП
Что такое "приватная зона отлова ошибок"? Некий try, сидящий в глубине?
источник

АГ

Александр Гранин... in ФП
Вообще, описание задачи довольно расплывчатое
источник

IZ

Ilia Zviagin in ФП
Daniil Kostin
У меня основная проблема, что транзакция в моем окружении - функция с приватной зоной отлова ошибок. И мне надо внедрить управление внутрь каждой такой функции через транзакцию уже моей реализации. Или писать ORM свое.
Мне кажется, что у тебя в голове всё перемешано в адской мешанине...
Не знаю, может я неправ — это было бы хорошо.
источник

DK

Daniil Kostin in ФП
Александр Гранин
Может, мне лучше порекомендовать свою книгу? Там это описано
я только за.
я код понимаю, но сам пока в ФП мало что могу написать. Только простенькое - операции над завернутыми числами.
источник

АГ

Александр Гранин... in ФП
источник

JS

Jerzy Syrowiecki in ФП
Александр Гранин
Вот здесь есть проблема. Не всякое IO действие можно откатить. И общего алгоритма rollback не существует
а также, наверно, есть большая разница между "в случае ошибки откатить, и конец" и "в случае ошибки откатить и снова пробовать до успеха"
источник