Translate

lunes, 5 de enero de 2026

Métodos Monádicos en Rust

Rust no tiene palabras como mónada en su sintaxis, pero su sistema de tipos y métodos encadenados son monádicos por naturaleza.

Gracias a eso, se pueden escribir programas expresivos y seguros, sin null, sin excepciones y sin estructuras de control complejas.

Una mónada representa un valor junto con un contexto (por ejemplo, “puede faltar” o “puede fallar”).

Provee operaciones para:

  • Aplicar una función al valor si está presente (map).
  • Encadenar funciones que también devuelven valores en contexto (and_then).
  • Definir valores alternativos (or, or_else).


En Rust, eso se aplica directamente a Option y Result.

Option<T> representa un valor que puede existir (Some) o no (None).


let x: Option<i32> = Some(5);

let y = x.map(|n| n * 2).and_then(|n| Some(n + 3));


println!("{:?}", y); // Some(13)


Los metodos que tenemos son : 

  • map(f): Aplica `f` al valor si existe
  • and_then(f): Encadena funciones que devuelven Option
  • or(opt): Usa otro valor si está vacío 
  • or_else(f): Calcula alternativa solo si es None


Ejemplo:


let res = None.or(Some(10)).map(|x| x * 2);

println!("{:?}", res); // Some(20)


Result modela operaciones que pueden tener éxito (Ok) o error (Err), sin excepciones.


fn parse_number(s: &str) -> Result<i32, String> {

    s.parse::<i32>().map_err(|_| "Invalid number".to_string())

}


Encadenamiento monádico:


let result = parse_number("42")

    .map(|x| x * 2)

    .and_then(|x| if x > 50 { Ok(x) } else { Err("too small") })

    .or_else(|_| Ok(0));


println!("{:?}", result); // Ok(84)


Si una función devuelve Err, el resto de la cadena se saltea automáticamente.

No hay try/catch, ni comprobaciones manuales.

Rust también permite componer funciones monádicas de forma declarativa:


fn half(n: i32) -> Option<i32> {

    if n % 2 == 0 { Some(n / 2) } else { None }

}


fn add_ten(n: i32) -> Option<i32> {

    Some(n + 10)

}


let result = Some(8)

    .and_then(half)

    .and_then(add_ten);


println!("{:?}", result); // Some(14)


Si en algún punto hay None, toda la cadena devuelve None.


El operador ?desempaqueta automáticamente Result o Option y corta la ejecución si no hay valor.


fn process() -> Result<i32, String> {

    let x = parse_number("10")?; // si falla, retorna Err automáticamente

    let y = parse_number("20")?;

    Ok(x + y)

}


Internamente, ? usa and_then y map, pero con una sintaxis más natural.

Rust no necesita hablar de mónadas — las usa en cada línea de código.