Mónadas (Monads) en Haskell
Si nos vamos al concepto tradicional de lo que es una mónada en Haskell tendremos lo siguiente:
"Una mónada es un patrón de diseño que estructura cálculos en una secuencia de pasos y maneja efectos secundarios de forma pura".
Se debe distinguir de la definición de Mónada hecha por el filósofo alemán Gottfried Wilhelm Leibniz. La cual dice:
"Una mónada es la base de todo lo existente; la materia espiritualizada".
Para Leibniz, es la substancia simple, única e independiente que compone la realidad en la que vivimos. Algunos más aventurados la considerarían el alma misma.
Mónadas
Una mónada es como una caja mágica que envuelve un valor y sabe cómo aplicar funciones a ese valor sin que tú tengas que preocuparte por los detalles.
En la programación funcional, una mónada (monad), es un patrón de diseño que representa cálculos definidos como una secuencia de pasos, permitiendo componer funciones con tipos incompatibles encapsulándolos en un tipo monádico.
Un tipo de dato con una estructura mónada define lo que simboliza en un bloque de código, o anida funciones del mismo tipo.
Mónada en Haskell
La mejor forma de entender lo que es una mónada es ver su sintaxis, la cual se define mediante la clase de tipos Monad y se utiliza principalmente con las funciones return y el operador bind (>>=), o mediante la notación do.
La mónada es como un patrón de organización para manejar efectos: errores, listas, entrada/salida, etc.
La clave está en dos operaciones:
return (o pure): mete un valor en la caja.
-
>>= (bind): aplica una función que devuelve otra caja, y se encarga de encadenarlas.
Usando Maybe
Ejemplo 1. Necesitamos sumar números, pero alguno podría ser Nothing (como un valor faltante).
sumaMaybe.hs
-- Función que suma dos valores dentro de Maybe sumaMaybe :: Maybe Int -> Maybe Int -> Maybe Int sumaMaybe mx my = do x <- mx y <- my return (x + y)
Como podemos observar, la opción de tipo Maybe a ("tal vez un"), representando un valor que es o un valor del tipo a , o ninguno.
Entramos al REPL de Haskell y cargamos el programa:
$ ghci ghci> :l sumaMaybe.hs
Aplicando la función tenemos:
sumaMaybe (Just 3) (Just 5) -- Resultado: Just 8 sumaMaybe Nothing (Just 5) -- Resultado: Nothing
Encadenando operaciones con Monads
Una mónada encadena operaciones sin que tengas que escribir toda la lógica de control (qué pasa si hay error, si falta un valor, etc.).
- En Maybe, la mónada se encarga de propagar el Nothing automáticamente.
- En IO, la mónada organiza acciones de entrada/salida en orden.
- En List, la mónada maneja combinaciones de elementos.
Una mónada es una forma elegante de encadenar cálculos con contexto (puede ser error, IO, listas, etc.) sin que tú tengas que repetir la lógica cada vez.
Ejemplo 2. Tomamos la lista [0,1,2,3,4,5] y, para cada número, generamos una lista con el número y su doble.
ejemploDo.hs
ejemploDo :: [Int] ejemploDo = do x <- [0,1,2,3,4,5] -- toma cada elemento de la lista [x, 2*x] -- devuelve una lista con el número y su doble
Entramos al REPL de Haskell y cargamos el programa:
$ ghci ghci> :l ejemploDo.hs
Aplicando la función tenemos:
ejemploDo -- [0,0,1,2,2,4,3,6,4,8,5,10]
Usos principales de las mónadas en Haskell
Entrada/Salida (IO)
La mónada IO organiza acciones como leer del teclado, escribir en pantalla o acceder a archivos.
main :: IO () main = do putStrLn "¿Cuál es tu nombre?" nombre <- getLine putStrLn ("Hola, " ++ nombre)
Sin la mónada IO, sería imposible encadenar operaciones de entrada/salida de forma pura.
Manejo de errores y valores opcionales (Maybe)
Evita tener que comprobar manualmente si un valor existe.
Propaga automáticamente el Nothing sin que el programador escriba lógica repetitiva.
dividir :: Int -> Int -> Maybe Int dividir _ 0 = Nothing dividir x y = Just (x `div` y)
Errores con mensajes (Either)
Similar a Maybe, pero permite adjuntar información sobre el error.
safeRoot :: Double -> Either String Double safeRoot x | x < 0 = Left "No se puede raíz negativa" | otherwise = Right (sqrt x)
Listas
La mónada de listas genera combinaciones y secuencias de valores.
pares :: [(Int, Int)] pares = do x <- [1,2,3] y <- [4,5] return (x,y) -- Resultado: [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)]
Estado (State)
Permite manejar variables que cambian a lo largo de un cálculo, sin perder la pureza funcional. Ejemplo típico: contadores, acumuladores, simulaciones.
Mónadas combinadas (transformers)
Se pueden apilar para manejar varios efectos a la vez (por ejemplo, MaybeT IO para entrada/salida con posibilidad de fallo).
En resumen:
Los usos más habituales de las mónadas en Haskell son:
- IO : entrada/salida ordenada.
- Maybe/Either: manejo de errores y valores opcionales.
- List: combinaciones y secuencias.
- State: estado mutable controlado.
- Transformers: combinar efectos.
Las mónadas son una característica de la programación funcional y del lenguaje Haskell. Continuaremos más sobre el tema en próximas entregas.
Enlaces:
https://es.wikipedia.org/wiki/M%C3%B3nada_(programaci%C3%B3n_funcional)


Comentarios
Publicar un comentario