Oℕ
сейчас я переписываю код, который будет работать как симуляция конкаренси
там очень важно, чтобы код выполнялся пошагово, чтобы с одной стороны можно было бы симулировать неопределённость выполнения
т.е. переключаться в любой момент с шага в одной симуляции треда на другой
а с другой стороны важно, чтобы эта "неопределённость" была полностью контролируема, т.е. поймав один раз мерцающий баг - ты бы мог запустить код и он отработал бы в точно таком же порядке
а потом добавить трассировок -и он всё равно продолжил бы выполняться в таком порядке
поэтому мне нужно сочетание Free, EitherT и StateT, если это всё наслаивать друг на друга - получается очень плохо воспринимаемый и отлаживаемый код
а если сделать сразу толстую штуку, отвязанную от области применения. хорошо её независимо оттестить, я буду относительно уверен, что баги в моей реализации не будут от того, как я делаю цикл обхода
разделяю на ортогональные концепты
в результате эту штуку можно будет применять в тофу - пишешь конкурентный код на тофу абстракциях, а дальше его тестируешь на абсолютно контролируемом виртуальном тестовом энвайроменте, и если поймаешь ошибку - всегда сможешь ровно с таким же сидом запустить, в отладке посмотреть в каждый момент времени значения всех стейтов, они будут вектором большим
посмотреть, что сейчас работает и на каком этапе, добавить сообщения для трассировки, но не потерять ценный кейс, в котором у тебя воспроизводится ошибка
это один из примеров, почему конкаренси нужно делать с интерпретируемыми типами, т.е. хотя бы теглесс файнал, а не в грязной колбечной форме, как это предлагают все современные библиотеки из коробки