我一直在使用Haxl
monad(这里描述:http://www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk),它有一个有趣的特性,<*>
其应用实例与Control.Monad的ap
不同。这是一个关键特性,可以在不阻塞的情况下进行并发计算。例如,如果hf
和ha
长计算,然后MaybeT m的应用实例假定Monad m
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
monad变压器吗?有没有办法避开ghc给我的“重复实例声明”的抱怨,如果我试着写上面的话?
我也想知道:目前的设置是否存在变压器封装的设计缺陷?如果不是,为什么不呢?
每个人都倾向于认为超类实现完全匹配子类实现。哈克斯尔违反了这条不成文的规则,因此无法与其他人打好关系。变形金刚也假设你正在制造'Monad'变形金刚,因此它的实施。 'Applicative'“变形金刚”有更好的结构。 –
@ J.Abrahamson,这不是一个规则,书面或其他。这也不是唯一的情况,其中'<*>'比'ap'更有效。在我看来'MaybeT'在这里是错误的。 – dfeuer
After [AMP](https://www.haskell。org/haskellwiki/Functor-Applicative-Monad_Proposal)作为GHC 7.10的一部分广泛传播,我们可以重写'Applicative(MaybeT m)'定义。目前'Applicative'不是'Monad'的超类,所以你可能会破坏大量的包。我还看到很多* Foo是Monad的实例,但不是应用程序*警告。会建议现在写你自己的'MaybeT',或者可能做一个PR到'变形金刚'?. – phadej