В более общем плане то, что вы пытаетесь сделать, - это применить преобразование к внутреннему слою стека трансформаторов. Для двух произвольных монад сигнатура типа может выглядеть примерно так:
fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 a) -> t m1 a -> t m2 a
В основном на более высоком уровне fmap
. На самом деле, вероятно, было бы даже более разумно объединить его с картой по последнему параметру:
fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 b) -> t m1 a -> t m2 b
Ясно, что это будет возможно не во всех случаях, хотя, когда "исходная" монада Identity
, это, вероятно, будет проще, но я могу представить определение другого класса типов для тех мест, где он действительно работает. Я не думаю, что в типичных библиотеках преобразователей монад есть что-то подобное; однако при просмотре информации о взломе обнаруживается нечто очень похожее в Monatron
пакете:
class MonadT t => FMonadT t where
tmap' :: FunctorD m -> FunctorD n -> (a -> b)
-> (forall x. m x -> n x) -> t m a -> t n b
tmap :: (FMonadT t, Functor m, Functor n) => (forall b. m b -> n b)
-> t m a -> t n a
tmap = tmap' functor functor id
В сигнатуре для tmap'
типы FunctorD
в основном представляют собой специальные реализации fmap
вместо прямого использования экземпляров Functor
.
Кроме того, для двух конструкторов типов F и G типа Functor функция с типом (forall a. F a -> G a)
описывает естественное преобразование из F в G. Вполне возможно, что есть другая реализация карты преобразователя, которую вы хотите где-то в пакете category-extras
, но Я не уверен, какой будет теоретико-категориальная версия преобразователя монад, поэтому я не знаю, как ее можно назвать.
Поскольку tmap
требуется только экземпляр Functor
(который должен иметь любой Monad
) и естественное преобразование, а любое Monad
имеет естественное преобразование из Identity
монады, предоставленной return
, функция, которую вы хотите, может быть записана в общем для любого экземпляра FMonadT
как tmap (return . runIdentity)
- -предполагая, что "базовая" монада определяется как синоним преобразователя, применяемого к Identity
, во всяком случае, что обычно имеет место с библиотеками преобразователей.
Возвращаясь к вашему конкретному примеру, обратите внимание, что у Monatron действительно есть экземпляр FMonadT
для StateT
.
person
C. A. McCann
schedule
09.11.2010
g :: StateT [Int] IO Int
должен стоять. - person glguy   schedule 10.11.2010