Я использовал монаду Haxl
(описанную здесь: http://www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk), у которой есть интересная функция, которая <*>
для своего аппликативного экземпляра isn 't то же, что и ap
из Control.Monad. Это ключевая функция, позволяющая выполнять параллельные вычисления без блокировки. Например, если hf
и ha
являются длинными вычислениями, то
let hf :: Haxl (a -> b) = ...
ha :: Haxl a = ...
in do
f <- hf
a <- ha
return (f a)
будет выполнять их последовательно, а
hf <*> ha
будет выполнять их параллельно, а затем объединить результаты.
Я хотел бы иметь возможность запускать вычисления в MaybeT Haxl
, но проблема в том, что аппликативный экземпляр для MaybeT m
в пакете трансформаторов использует монадическое связывание:
instance (Functor m, Monad m) => Applicative (MaybeT m) where
pure = return
(<*>) = ap
Где ap = liftM2 id
- от Control.Monad
. Это делает
let hmf :: MaybeT Haxl (a -> b) = ...
hma :: MaybeT Haxl a = ...
in hmf <*> hma
запускается последовательно. Кажется, что лучший пример будет больше похож на
instance (Applicative m) => Applicative (MaybeT m) where
pure = MaybeT . pure . Just
MaybeT f <*> MaybeT x = MaybeT $ (<*>) <$> f <*> x
(Здесь (<*>)
в правой части для монады Maybe
, а в скобках <*>
в правой части для m
.) Обратите внимание, что контекст отличается - вышеупомянутый экземпляр принимает только Applicative m
, а экземпляр в трансформаторах принимает Functor m, Monad m
.
Мой главный вопрос практичен: что мне делать с этим? Должен ли я запускать собственный трансформатор монады MaybeT
? Есть ли способ обойти жалобу "Повторяющиеся экземпляры экземпляра", которую ghc дает мне, если я попытаюсь написать выше?
Я также хотел бы знать: является ли текущая установка дефектом дизайна в пакете трансформаторов? Если нет, почему бы и нет?