Учитывая две монады, Monad m
и Monad n
, я хотел бы преобразовать m (n a)
в n (m a)
.Но, похоже, нет общего способа, потому что и (>>=)
, и return
имеют дело только с одним типом монад, и хотя (>>=)
позволяет извлекать контент из монады, вы должны упаковать его обратно в тот же тип монады, чтобы он мог бытьзначение результата.
Однако, если мы установим для m
фиксированный тип, задание станет простым.Возьмем Maybe
в качестве примера:
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')
Нетрудно увидеть, у нас здесь есть образец.Чтобы быть более очевидным, напишите это Applicative
способом, и это не более чем применение конструктора данных к каждому элементу:
reorder (Just x) = Just <$> x
reorder (x:xs) = (:) <$> x <*> (reorder xs)
Мой вопрос: существует ли класс типов haskell для описания таких операций?или я должен сам изобрести колесо?
Я провел краткий поиск в документации GHC и не нашел ничего полезного для этой темы.