Переупаковка монад — любой общий способ?

Даны две монады, 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 и не нашел ничего полезного по этой теме.

13
задан Riccardo T. 13 March 2012 в 13:49
поделиться