Dadas dos mónadas, Monad m
y Monad n
, me gustaría transformar m (n a)
en n (m a)
. Pero parece que no hay una forma genérica porque (>>=)
y return
tratan con un solo tipo de mónada, y aunque (>>=)
permite extraer contenido de una mónada, debe empacarlos al mismo tipo de mónada para que pueda ser un valor de resultado.Reempazar mónadas: ¿una forma genérica?
Sin embargo, si configuramos m
en un tipo fijo, el trabajo es fácil. Tome Maybe
como ejemplo:
reorder :: (Monad n) => Maybe (n a) -> n (Maybe a)
reorder Nothing = return Nothing
reorder (Just x) = do
x' <- x
return $ Just x'
o una lista:
reorder :: (Monad n) => [n a] -> n [a]
reorder [] = return []
reorder (x:xs) = do
x' <- x
xs' <- reorder xs
return (x':xs')
No es difícil de ver, tenemos un patrón aquí. Para ser más claro, escribirlo de una manera Applicative
, y no es más que aplicar el constructor de datos para cada elemento:
reorder (Just x) = Just <$> x
reorder (x:xs) = (:) <$> x <*> (reorder xs)
Mi pregunta es: hace una clase de tipos de Haskell ya existen para describir este tipo de operaciones, o tengo tengo que inventar la rueda yo mismo?
Tuve una breve búsqueda en la documentación de GHC, y no encontré nada útil para este tema.
Esto, por supuesto, solo funciona cuando el constructor de tipo externo es un 'Traversable' (no todos los 'Monad's son). La ventaja es que el interno solo tiene que ser 'Aplicativo'. –