Una mónada es un tipo que encapsula un valor junto con un contexto (por ejemplo, “puede fallar” o “puede faltar”).
Los métodos monádicos permiten operar dentro de ese contexto sin “salir” de él.
En C++:
std::optional<T> encapsula un valor o nada.
std::expected<T, E> encapsula un valor o un error.
Veamos los metodos:
transform
Aplica una función al valor si existe, y devuelve un nuevo objeto del mismo tipo.
std::optional<int> x = 5;
auto y = x.transform([](int n){ return n * 2; }); // y = 10
Si x no tiene valor, transform no hace nada.
and_then
Encadena operaciones que también devuelven std::optional o std::expected.
auto divide = [](int n) -> std::optional<int> {
return n == 0 ? std::nullopt : 100 / n;
};
std::optional<int> x = 5;
auto r = x.and_then(divide); // aplica divide(5)
Si en cualquier paso hay std::nullopt, toda la cadena devuelve std::nullopt.
or_else
Permite especificar una acción alternativa si no hay valor.
std::optional<int> x = std::nullopt;
x.or_else([]{ return std::optional(42); }); // devuelve 42
Ideal para valores por defecto o recuperación de errores.
En std::expected<T, E>, los métodos monádicos también existen:
std::expected<int, std::string> parse(std::string s);
auto result = parse("42")
.transform([](int x){ return x * 2; })
.and_then([](int x) -> std::expected<int, std::string> {
return x > 50 ? std::unexpected("too big") : x;
})
.or_else([](auto err){
std::cerr << "Error: " << err << "\\n";
return std::expected<int, std::string>(0);
});
Así se evita usar try/catch o múltiples if para cada paso.
¿Y por qué tengo que usar estos métodos?
- Código más limpio y expresivo.
- Sin necesidad de desempaquetar (.value() / .has_value()).
- Naturalmente componible y seguro.
- Permite escribir funciones sin excepciones pero con semántica clara de error.
Los métodos monádicos son una de las adiciones más elegantes del C++ moderno, te permiten escribir código más funcional, más seguro y más declarativo.
