Sam Halliday интересно рассказал о потенциальных уязвимостях в библиотеках для парсинга JSON. А ещё о том, как боролся с ними в своей библиотеке
Красивая фраза в описании доклада: «Scala has more JSON libraries than Go has language features!»
https://youtu.be/3Cz6D8JLSSA
Красивая фраза в описании доклада: «Scala has more JSON libraries than Go has language features!»
https://youtu.be/3Cz6D8JLSSA
Доклад Adam Warski о том, как метапрограммировать в третьей скале
Меня больше всего заинтересовала часть о деривации тайпклассов: фича мощная, а документации дотти мне не хватило, чтобы её осмыслить. В целом она реализована не то чтобы сложно, а скорее громоздко. То есть концептуально всё вроде понятно, но чтобы написать что-то осмысленное, каждый раз придётся пыхтеть над документацией и компилятором. Радует только то, что сейчас деривация всяких кодеков делается макросами, которые читать и писать ещё сложнее.
Видео: https://www.youtube.com/watch?v=leIB5tvDY64
Исходники из доклада: https://github.com/adamw/scala3-macro-pres
Меня больше всего заинтересовала часть о деривации тайпклассов: фича мощная, а документации дотти мне не хватило, чтобы её осмыслить. В целом она реализована не то чтобы сложно, а скорее громоздко. То есть концептуально всё вроде понятно, но чтобы написать что-то осмысленное, каждый раз придётся пыхтеть над документацией и компилятором. Радует только то, что сейчас деривация всяких кодеков делается макросами, которые читать и писать ещё сложнее.
Видео: https://www.youtube.com/watch?v=leIB5tvDY64
Исходники из доклада: https://github.com/adamw/scala3-macro-pres
Forwarded from Consensus
📚 Классный open source курс по распределенным системам от PingCap:
👉 https://github.com/pingcap/talent-plan
В этом курсе можно зафигачить Raft и Percolator на rust.
Либо на golang сделать распределенную key-value или relational базу данных.
В курсе все подробно расписано по шагам. Подойдет для тех, кто имеет минимальный опыт на golang/rust и умеет пользоваться гитом. Курс не подойдет тем, кто хочет выучить язык с нуля(вначале придется прочитать Rust Book или пройти A Tour of Go, этого будет достаточно).
👉 https://github.com/pingcap/talent-plan
В этом курсе можно зафигачить Raft и Percolator на rust.
Либо на golang сделать распределенную key-value или relational базу данных.
В курсе все подробно расписано по шагам. Подойдет для тех, кто имеет минимальный опыт на golang/rust и умеет пользоваться гитом. Курс не подойдет тем, кто хочет выучить язык с нуля(вначале придется прочитать Rust Book или пройти A Tour of Go, этого будет достаточно).
GitHub
GitHub - pingcap/talent-plan: open source training courses about distributed database and distributed systems
open source training courses about distributed database and distributed systems - pingcap/talent-plan
Разбор «бессерверных» архитектур на сайте Фаулера заставил крепко задуматься. С одной стороны FaaS даёт максимальную гранулярность компонент и легчайшее горизонтальное масштабирование. С другой стороны добавляются проблемы с задержкой из-за холодных стартов и оркестрацией циклопических графов зависимостей между серверлесс-компонентами. А серверлесс — это не только самописные функции, но и внешние проприетарные бэкенды, с которыми тоже надо как-то жить (например, Auth0).
Касательно применимости кажется, что реалтаймовые API в FaaS особо не засунешь как раз из-за холодных стартов. А вот консюмеры-шедулеры на формат FaaS ложатся отлично: им задержка на старте не страшна. Это удобно, потому что сбой отдельного процесса проще мониторить в изоляции от остальных, ну и автоскейлинг в придачу. Для переиспользования кода можно держать несколько функций в одном репозитории, как и в обычном сервисе. Провайдеру доставлять джарник с общим кодом и указание в конфиге, какую из функций надо дёрнуть.
Всё это выглядит как неминуемо приближающееся будущее.
https://martinfowler.com/articles/serverless.html
Касательно применимости кажется, что реалтаймовые API в FaaS особо не засунешь как раз из-за холодных стартов. А вот консюмеры-шедулеры на формат FaaS ложатся отлично: им задержка на старте не страшна. Это удобно, потому что сбой отдельного процесса проще мониторить в изоляции от остальных, ну и автоскейлинг в придачу. Для переиспользования кода можно держать несколько функций в одном репозитории, как и в обычном сервисе. Провайдеру доставлять джарник с общим кодом и указание в конфиге, какую из функций надо дёрнуть.
Всё это выглядит как неминуемо приближающееся будущее.
https://martinfowler.com/articles/serverless.html
Forwarded from PONV Daily (Danila Matveev)
#scala #tf
Опубликовали лекцию с рассказом и кодом о тэглесс файнал. Она адресована прежде всего тем кто не знает, что это такое, или изучавшим по твиттам Де Гуза, Трампа и роскомнадзора. Но полезна может быть всем.
Если вам интересна эта тема, хотите видеть продолжения, готовы поддержать лектора и его команду:
* Подписывайтесь на ютуп канал.
* Ставьте колокольчик.
* Задавайте вопросы в комментариях ютупа, в этом чате, в тофу чате.
* Пишите код на работе и в личных проектах, помогайте кодом и документацией чужим опен сорсам.
https://www.youtube.com/watch?v=ZNK57IXgr3M
Опубликовали лекцию с рассказом и кодом о тэглесс файнал. Она адресована прежде всего тем кто не знает, что это такое, или изучавшим по твиттам Де Гуза, Трампа и роскомнадзора. Но полезна может быть всем.
Если вам интересна эта тема, хотите видеть продолжения, готовы поддержать лектора и его команду:
* Подписывайтесь на ютуп канал.
* Ставьте колокольчик.
* Задавайте вопросы в комментариях ютупа, в этом чате, в тофу чате.
* Пишите код на работе и в личных проектах, помогайте кодом и документацией чужим опен сорсам.
https://www.youtube.com/watch?v=ZNK57IXgr3M
YouTube
Tofu club. Что такое tagless final?
Что такое TF на самом деле? Когда он нужен, а когда нет?
Документальный полнометражный фильм, который раскрывает тайну Олега Киселева и по пути проверяет готовность Dotty (Scala 3).
В главных ролях Олег Нижников и VS Code. Репозиторий с кодом https://…
Документальный полнометражный фильм, который раскрывает тайну Олега Киселева и по пути проверяет готовность Dotty (Scala 3).
В главных ролях Олег Нижников и VS Code. Репозиторий с кодом https://…
Отладка grpc-сервисов с радостью и улыбкой
Ну очень крутая штука для отладки grpc-сервисов (если на сервере включена рефлексия).
https://github.com/fullstorydev/grpcui
Просто пишешь в терминале
Для запросов не из UI, а из командой строки есть grpcurl. Там тоже можно получить список методов сервиса и прочие ништяки.
И в отличие от http это всё идёт из коробки, не надо генерировать или описывать сваггер.
Ну очень крутая штука для отладки grpc-сервисов (если на сервере включена рефлексия).
https://github.com/fullstorydev/grpcui
Просто пишешь в терминале
grpcui -plaintext localhost:6000
, чтобы в браузере появилась админка к сервису, построенная по его прото-схеме. Причём там не просто отображается список методов, но и поля запроса рендерятся в нужный тип UI-контролов.Для запросов не из UI, а из командой строки есть grpcurl. Там тоже можно получить список методов сервиса и прочие ништяки.
И в отличие от http это всё идёт из коробки, не надо генерировать или описывать сваггер.
К началу 2021 года уже забыл о существовании
Без goto это пришлось бы писать вложенным циклом, нужным не для всех веток условий. Причём не сказал бы, что рефакторинг этой процедуры с устранением
https://github.com/VictoriaMetrics/VictoriaMetrics/blob/e59de98384481d7873c8eca35be8d0ad9d598bb6/lib/storage/part_search.go#L229-L277
goto
, но оказалось, что в голанге его вполне себе пишут. С помощью @oleg_log нашёл пример даже элегантного использования: внутри итерации цикла возврат на её начало с изменением внешнего стейта.Без goto это пришлось бы писать вложенным циклом, нужным не для всех веток условий. Причём не сказал бы, что рефакторинг этой процедуры с устранением
goto
упростил бы её код.https://github.com/VictoriaMetrics/VictoriaMetrics/blob/e59de98384481d7873c8eca35be8d0ad9d598bb6/lib/storage/part_search.go#L229-L277
Простая статья о том, как будет работать варианс в пересечённых и объединённых типах Scala 3. Если вкратце, то интуитивно, кроме контравариантных правил, которые моей интуиции почему-то не поддаются :c
Для ковариантного
–
–
Для контравариантного
–
–
–
https://ayushm4489.medium.com/union-and-intersection-types-in-scala-3-6b5f7e818dc4
Для ковариантного
C
:–
C[A] | C[B] <: C[A | B]
–
C[A & B] <: C[A] & C[B]
Для контравариантного
C
:–
C[A | B] <: C[A]
–
C[A | B] <: C[B]
–
C[A | B] <: C[A] & C[B]
https://ayushm4489.medium.com/union-and-intersection-types-in-scala-3-6b5f7e818dc4
Forwarded from Scala Nishtyaki Channel
Акка сенсоры в чяте!
Интересная статья + библиотека по акке и обсервабилити за авторством @zeehond:
Медиум: https://jacum.medium.com/observability-of-a-reactive-system-48d520c4cf69
Гитхаб: https://github.com/jacum/akka-sensors
Да, присылайте ваши билиотеки в личку, будем постить.
Интересная статья + библиотека по акке и обсервабилити за авторством @zeehond:
Медиум: https://jacum.medium.com/observability-of-a-reactive-system-48d520c4cf69
Гитхаб: https://github.com/jacum/akka-sensors
Да, присылайте ваши билиотеки в личку, будем постить.
Medium
Observability of a reactive system: Introducing Akka Sensors
Introducing Akka Sensors: Native Prometheus collectors for actors and dispatchers with low overhead.
Спивак опять красиво расписал про файберы
Какую проблему решают, в чём разница по сравнению с работой на тредах напрямую, как можно их шедулить.
https://typelevel.org/blog/2021/02/21/fibers-fast-mkay.html
Какую проблему решают, в чём разница по сравнению с работой на тредах напрямую, как можно их шедулить.
https://typelevel.org/blog/2021/02/21/fibers-fast-mkay.html
Сайт Мартина Фаулера — это кладезь энциклопедических знаний по разработке ПО. Помимо вещей, касающихся непосредственно программирования, у него формализованы подходы к IT «с высоты»: структура организаций, паттерны распределённых систем, процессы.
Continuous Delivery и Continuous Integration — короткие и понятные определения CI/CD, ключевые критерии, построение процессов;
Data Mesh Principles and Logical Architecture — управление большими аналитическими данными в децентрализованных организациях;
DevOpsCulture — просто нормальное определение DevOps;
Patterns of Distributed Systems — сборник паттернов вокруг консенсуса узлов распределённой системы;
How to break a Monolith into Microservices и How to extract a data-rich service from a monolith — пошаговые инструкции по выделению микросервисов из монолита.
Continuous Delivery и Continuous Integration — короткие и понятные определения CI/CD, ключевые критерии, построение процессов;
Data Mesh Principles and Logical Architecture — управление большими аналитическими данными в децентрализованных организациях;
DevOpsCulture — просто нормальное определение DevOps;
Patterns of Distributed Systems — сборник паттернов вокруг консенсуса узлов распределённой системы;
How to break a Monolith into Microservices и How to extract a data-rich service from a monolith — пошаговые инструкции по выделению микросервисов из монолита.
Доклад Alexander Ioffe о выводе тайпклассов в третьей скале. В начале он рассматривает проблему рефлексии против макросов при сериализации классов. Я жил с интуитивным пониманием, что макросы быстрее рефлексии, но ленился померять, насколько. А вот докладчик не поленился! Дальше идёт хардкорное метапрограммирование, о котором кому, как не кор-контрибутору quill рассказывать.
Видео: https://www.youtube.com/watch?v=E9L1-rkYPng
Исходники из доклада: https://github.com/deusaquilus/derivation_examples
Видео: https://www.youtube.com/watch?v=E9L1-rkYPng
Исходники из доклада: https://github.com/deusaquilus/derivation_examples
В соседнем канале серия постов про ошибки в работе с реляционными БД, и это прямо ценно
https://www.tg-me.com/nosingularity/737
https://www.tg-me.com/nosingularity/738
https://www.tg-me.com/nosingularity/739
https://www.tg-me.com/nosingularity/737
https://www.tg-me.com/nosingularity/738
https://www.tg-me.com/nosingularity/739
Telegram
Сингулярности не будет (18+)
Переходим к поиску проблем в схеме БД.
Первый документ, который стоит изучить: https://wiki.postgresql.org/wiki/Don't_Do_This
Там вы найдете небольшое количество правил, которые легко учесть при разработке, если вы не используете ORM.
Но на что еще нам стоит…
Первый документ, который стоит изучить: https://wiki.postgresql.org/wiki/Don't_Do_This
Там вы найдете небольшое количество правил, которые легко учесть при разработке, если вы не используете ORM.
Но на что еще нам стоит…
Бытует мнение, что в Scala сложно вкатиться начинающему программисту: всем нужны разработчики middle+ уровня. Это близко к правде, я сам довольно долго искал первую работу. Но теперь рынок труда перевернулся и вакансия для начинающих скалистов есть!
В Яндекс.Вертикали набираем стажёров на наши Scala-бэкенды. Если вы только начинаете свою карьеру и уже хотите войти в чудесный мир монадок и распределённых систем — спешите подавать заявку, количество место ограничено!
Подать заявку на стажировку -> https://yandex.ru/jobs/vacancies/dev/intern_backend_auto/
А ещё у нас грандиозные планы по найму «взрослых» программистов. Подробно почитать про вакансию можно здесь -> https://telegra.ph/Vakansiya-behkend-razrabotchika-na-Scala-03-04.
TL;DR:
- делаем auto.ru, Я.Недвижимость и Я.Объявления
- любим ФП;
- открыты к общению как с опытными скалистами, так и разработчиками из других стеков (желательно около-jvm);
- есть команды с интенсивной продуктовой разработкой, есть команды, занимающиеся инфраструктурными решениями;
- всегда нужны тимлиды, приходите к нам и становитесь руководителями;
- total складывается из оклада, премий, RSU и кучи неденежных компенсаций (ДМС, скидки у партнёров);
- надо пройти два собеса: общие вопросы с лайвкодингом и system design.
CV и вопросы можно писать мне в личку @poslegm
В Яндекс.Вертикали набираем стажёров на наши Scala-бэкенды. Если вы только начинаете свою карьеру и уже хотите войти в чудесный мир монадок и распределённых систем — спешите подавать заявку, количество место ограничено!
Подать заявку на стажировку -> https://yandex.ru/jobs/vacancies/dev/intern_backend_auto/
А ещё у нас грандиозные планы по найму «взрослых» программистов. Подробно почитать про вакансию можно здесь -> https://telegra.ph/Vakansiya-behkend-razrabotchika-na-Scala-03-04.
TL;DR:
- делаем auto.ru, Я.Недвижимость и Я.Объявления
- любим ФП;
- открыты к общению как с опытными скалистами, так и разработчиками из других стеков (желательно около-jvm);
- есть команды с интенсивной продуктовой разработкой, есть команды, занимающиеся инфраструктурными решениями;
- всегда нужны тимлиды, приходите к нам и становитесь руководителями;
- total складывается из оклада, премий, RSU и кучи неденежных компенсаций (ДМС, скидки у партнёров);
- надо пройти два собеса: общие вопросы с лайвкодингом и system design.
CV и вопросы можно писать мне в личку @poslegm
Forwarded from Anton Trunov
Всем привет! Мы хотим организовать неформальную летнюю школу по формальным методам и всяким родственным штукам (см. WIP сайт школы https://лялямбда.рус).
Планируются мини-курсы/воркшопы/доклады/нетворкинг/развлечения.
Темы курсов и воркшопов ещё пока только определяются (предложите свою!) и простираются от рандомизированного тестирования/фаззинга и модел-чекинга, до кубических (и не только) пруверов, логики некорректности, верифицированных компиляторов и слабых моделей памяти. Мы приветствуем участников с любым уровнем знаний — планируются несколько треков, чтобы каждый мог выбрать себе тему по своему бэкграунду.
Чтобы понять больше о наших потенциальных участниках и о том, какой формат школы выбрать, нам нужна ваша помощь: если бы вы хотели поехать, заполните, пожалуйста, небольшую форму https://docs.google.com/forms/d/e/1FAIpQLScfJ3tguxHNgxwHX_XpsWOiABTwB2R74sKh6OXEmcpYCCQqOQ/viewform.
Планируются мини-курсы/воркшопы/доклады/нетворкинг/развлечения.
Темы курсов и воркшопов ещё пока только определяются (предложите свою!) и простираются от рандомизированного тестирования/фаззинга и модел-чекинга, до кубических (и не только) пруверов, логики некорректности, верифицированных компиляторов и слабых моделей памяти. Мы приветствуем участников с любым уровнем знаний — планируются несколько треков, чтобы каждый мог выбрать себе тему по своему бэкграунду.
Чтобы понять больше о наших потенциальных участниках и о том, какой формат школы выбрать, нам нужна ваша помощь: если бы вы хотели поехать, заполните, пожалуйста, небольшую форму https://docs.google.com/forms/d/e/1FAIpQLScfJ3tguxHNgxwHX_XpsWOiABTwB2R74sKh6OXEmcpYCCQqOQ/viewform.
Google Docs
Логистика Лялямбда '21
Финализируем даты школы с вашей обратной связью. http://лялямбда.рус
Лонгрид Профессора об экспериментальном механизме контроля исключений в Scala 3
Пока закрыто экспериментальным флагом компилятора. Выглядеть будет так:
Чем мотивируется? Асинхронный код на Scala пишется с использованием какой-то монадки, в которую контроль ошибок так или иначе встроен. Но для синхронного кода надо или жить с unchecked эксепшенами, либо втаскивать монадку
Джавовые checked эксепшены неудобны и требует дыры в виде
Для примера выше компилятор сгенерирует код
Механика позволит отказаться от лишних монадок в некотором коде. Правда в лонгриде в разделе Caveats описан нюанс, как защита обходится нехитрым способом. Возможно, потом это исправят.
Чтобы
Про исключения: https://github.com/dotty-staging/dotty/blob/add-safe-throws-2/docs/docs/reference/experimental/canthrow.md
Про erased: https://github.com/dotty-staging/dotty/blob/master/docs/docs/reference/metaprogramming/erased-terms.md
Пока закрыто экспериментальным флагом компилятора. Выглядеть будет так:
def f(x: Double): Double canThrow LimitExceeded =
if x < limit then x * x else throw LimitExceeded()
@main def test(xs: Double*) =
try println(xs.map(f).sum)
catch case ex: LimitExceeded => println("too large")
Чем мотивируется? Асинхронный код на Scala пишется с использованием какой-то монадки, в которую контроль ошибок так или иначе встроен. Но для синхронного кода надо или жить с unchecked эксепшенами, либо втаскивать монадку
Either
только чтобы зафиксировать ошибку в сигнатуре.Джавовые checked эксепшены неудобны и требует дыры в виде
RuntimeException
. Поэтому Одерски придумал новую механику. Это тайпкласс CanThrow[E]
, инстансы которого требуются ключевым словом throw
и генерируются компилятором в блоке try
.Для примера выше компилятор сгенерирует код
@main def test(xs: Double*) =
try
erased given ctl: CanThrow[LimitExceeded] = ???
println(xs.map(x => f(x)(using ctl)).sum)
catch case ex: LimitExceeded => println("too large")
Механика позволит отказаться от лишних монадок в некотором коде. Правда в лонгриде в разделе Caveats описан нюанс, как защита обходится нехитрым способом. Возможно, потом это исправят.
Чтобы
canThrow
не создавал оверхеда в рантайме, для него используется новое ключевое слово erased. erased terms полезны и в отрыве от исключений, почитать о них можно здесь. Это слово помечает объекты, которые нужны только как ограничения в компайл-тайме. Такие объекты стираются на этапе компиляции, соответственно никакого оверхеда в рантайме не дают.Про исключения: https://github.com/dotty-staging/dotty/blob/add-safe-throws-2/docs/docs/reference/experimental/canthrow.md
Про erased: https://github.com/dotty-staging/dotty/blob/master/docs/docs/reference/metaprogramming/erased-terms.md
Наткнулся на старый тикет, в котором Travis Brown померял производительность вызова
Что с этим делать? Да ничего. Если у вас есть горячий код с фолдами, то вы, скорее всего, уже давно всё заинлайнили. Если код холодный, то оверхед вы и не заметите.
https://github.com/typelevel/cats/issues/1951
fold
по сравнению с обычным паттерн-матчингом. Замеры он делал для cats.data.Validated
, но результаты актуальны и для аналогичных контейнеров (Either
, Option
). А результаты неутешительные — fold
медленнее заинлайненного паттерн-матчинга в четыре раза. fold
для этих типов реализован тривиально и фактически принимает две функции, чтобы засунуть их в паттерн-матчинг:sealed abstract class Validated[+E, +A] {Просадка производительности связана с тем, как в jvm реализованы лямбды: для каждой лямбды аллоцируется объект в куче. Соотвественно
// ...
def fold[B](fe: E => B, fa: A => B): B = this match {
case Invalid(e) => fe(e)
case Valid(a) => fa(a)
}
// ...
}
Validated // <- медленно
.valid(42)
.fold(e => println(s"error $e"), res => println(s"result $res"))
Validated.valid(42) match { // <- быстро
case Invalid(e) => println(s"error $e")
case Valid(res) => println(s"result $res")
}
fold
только и делает, что аллоцирует лямбды для своих аргументов.Что с этим делать? Да ничего. Если у вас есть горячий код с фолдами, то вы, скорее всего, уже давно всё заинлайнили. Если код холодный, то оверхед вы и не заметите.
https://github.com/typelevel/cats/issues/1951
В качестве упражнения с макросами накодякал библиотечку, которая генерит конструкторы для кейс-классов с зарефайненными полями.
https://github.com/poslegm/brief
Зачем это нужно:
1. Типобезопасно провалидированные поля кейс-классов;
2. Вместо fail-fast валидации аккумулировать ошибки по всем полям;
3. В сообщениях об ошибках видеть названия проблемных полей и что пошло не так;
4. При этом не писать тонны бойлерплейта.
В планах устранение ограничений (не поддерживаются классы с тайп-параметрами и тайп-алиасы для полей) и миграция на Scala 3. Зависимость только на refined.
Скорее всего аналогичные библиотеки уже существуют, но они очевидно имеют фатальный недостаток. Возможно, и моё поделие будет кому-нибудь полезно.
До начала работы над этой либой макросы устрашали, а оказалось, что нехитрая кодогенерация на них делается без особых сложностей.
https://github.com/poslegm/brief
Зачем это нужно:
1. Типобезопасно провалидированные поля кейс-классов;
2. Вместо fail-fast валидации аккумулировать ошибки по всем полям;
3. В сообщениях об ошибках видеть названия проблемных полей и что пошло не так;
4. При этом не писать тонны бойлерплейта.
В планах устранение ограничений (не поддерживаются классы с тайп-параметрами и тайп-алиасы для полей) и миграция на Scala 3. Зависимость только на refined.
Скорее всего аналогичные библиотеки уже существуют, но они очевидно имеют фатальный недостаток. Возможно, и моё поделие будет кому-нибудь полезно.
До начала работы над этой либой макросы устрашали, а оказалось, что нехитрая кодогенерация на них делается без особых сложностей.
Adam Warski написал блогпост с подробным разбором context functions из Scala 3. Если вкратце, это возможность описать тип функции с implicit параметром. Например:
Изначально я их воспринимал просто как возможность задавать красивые тайп-алиасы, чтобы не писать постоянно
У меня глаз зацепился за один из примеров применения — проброс соединения к БД через методы для объединения их вызовов в одну транзакцию. То есть использование некоего
Это даёт больше гибкости в коде, но пропадает одна из моих любимых особенностей скаловых библиотек для работы с RDBMS: функции, обращающиеся к базе, оперируют специфичной монадкой (
https://blog.softwaremill.com/context-is-king-20f533474cb3
type Executable[T] = ExecutionContext ?=> Future[T]
Изначально я их воспринимал просто как возможность задавать красивые тайп-алиасы, чтобы не писать постоянно
(implicit ec: ExecutionContext)
. Но всё же это более мощный механизм, и Adam в своём посте это раскрывает.У меня глаз зацепился за один из примеров применения — проброс соединения к БД через методы для объединения их вызовов в одну транзакцию. То есть использование некоего
Connected[IO[T]]
вместо ConnectionIO[T]
из doobie. Это даёт больше гибкости в коде, но пропадает одна из моих любимых особенностей скаловых библиотек для работы с RDBMS: функции, обращающиеся к базе, оперируют специфичной монадкой (
ConnectionIO
/DBIO
), которая композится только с себеподобными, и не позволяет без костылей вкорячить в транзакцию какой-нибудь тормозной сайд-эффект. Разделять транзакционный код вокруг базы и внешние эффекты приложения на уровне типов — это здорово и безопасно.https://blog.softwaremill.com/context-is-king-20f533474cb3