Даны две монады, Monad m
и Monad n
, я хотел бы преобразовать m (na)
в n (ma)
. Но общего пути, по-видимому, нет, потому что и (>>=)
, и return
имеют дело только с одним типом монады, и хотя (>>=)
позволяет извлекая содержимое из монады, вы должны упаковать его обратно в тот же тип монады, чтобы он мог быть результирующим значением.
Однако, если мы установим для m
фиксированный тип, задание станет проще. Возьмем, к примеру, Может быть
:
reorder :: (Monad n) => Maybe (n a) -> n (Maybe a)
reorder Nothing = return Nothing
reorder (Just x) = do
x' <- x
return $ Just x'
Или список:
reorder :: (Monad n) => [n a] -> n [a]
reorder [] = return []
reorder (x:xs) = do
x' <- x
xs' <- reorder xs
return (x':xs')
Нетрудно заметить, что здесь у нас есть образец. Чтобы быть более очевидным, напишите его в аппликативном
виде, и это не более чем применение конструктора данных к каждому элементу:
reorder (Just x) = Just <$> x
reorder (x:xs) = (:) <$> x <*> (reorder xs)
Мой вопрос: существует ли уже класс типов Haskell для описания таких операций, или я должен сам изобретать колесо?
Я провел небольшой поиск в документации GHC и не нашел ничего полезного по этой теме.