Монада - инструмент, который позволяет создавать цепочки вызовов функций или методов без лишних проверок данных, которые возвращаются в предыдущем шаге. Монад много, но рассмотрим только популярные - 
Maybe, 
Result и 
Try.
* 
Maybe - оборачивает значение в 
Some или возвращает 
None объект без значения. 
* 
Result - оборачивает значение в 
Success или 
Failure.
* 
Try - оборачивает вызов кода в 
Result если не было эксепшенов и в 
Error, если код упал с ошибкой (которая ловится)
У каждой из монад есть 3 главных функции, 
fmap, 
bind и способ получить данные, которые содержит в себе монада.
* 
fmap - выполняет блок, если значение монады соответствует 
Success варианту, а результат выполнения блока оборачивает в ту же монаду, у которой он вызвался. Например: 
Some(1).fmap(&:to_s) # => Some('1')
None().fmap(&:to_s) # => Nothing
* 
bind - аналогичен 
fmap, только возвращается результат выполнения блока:
Some(1).bind(&:to_s) # => '1'
Some(1).bind { |value| Success(value) } # => Success('1')
None().bind(&:to_s) # => Nothing
В руби нет монад из коробки, но существуют гемы, которые реализуют монады:
* 
dry-monads* 
kleisli* 
tomstuart/monadsСоветую dry, как единственную поддерживаемую. К тому же, при использовании dry-validation можно легко конвертировать результат валидации в монаду, воспользовавшись экстеншеном:
Dry::Validation.load_extensions(:monads)
Это минимум, который нужен, чтобы начать использовать монады в руби приложении. Для закрепления - перепишем изначальный пример с использованием монад:
http.get(url, params) # теперь клиент возвращается Result Monad
  # валидация возвращает Result, который используется для следующих вызовов
  .bind { |body| validator.call(body).to_result }
  # сохраняем в базу, если валидация вернула Success
  .bind { |payload| Maybe(user_repository.create(payload)) }
  # вызываем воркер, если сохранение вернет Some
  .fmap { |user| NotificationWorker.perform_async(user.id) }
Кроме использования монад в бизнес логике, попробуйте эту абстракцию для обработки результата, который возвращается из бизнес логики. Как пример - вызов operation из экшена и последующая обработка результата в этом же экшене: 
cookie_box/show.rbЧто делать с результатомПри использовании 
dry-monads можно:
- вызывать на прямую 
success?, 
failed? или 
value_or;
- 
использовать `dry-matcher`;
- мой любимый вариант, 
использовать `case`;
Минусы1. В отличии от условий (
if, 
unless, etc) нельзя просто взять и использовать монаду. Если не знать в чем смысл абстракции и что значат 
bind и 
fmap - будет сложно понять код, который написан;
2. Использование монад может сильно усложнить код. Спасает опыт, а опыт получается в практике;
3.  Если хотите начать использовать монады в проекте, придется прорваться через ужас в глазах коллег (причина почему я написал этот текст);
Запомнить* Монады - абстракция для чейна вызовов функций и следованию railway programming;
* Для использования монад не нужно математическое образование. Главное понять, что монада оборачивает данные в объекты с единым интерфейсом;
* Советую начать с  - 
Maybe, 
Result и 
Try;
* 
fmap и 
bind - методы для чейна вызовов функций
* Чрезмерное использование монад усложняет код, будьте осторожны и подходите к написанию кода с умом;
Полезное* 
Как рефакторить руби код с монадами* 
Algebraic Data Types & Monads in Ruby* 
Monads and Ruby* 
Railway Oriented Programming