MaybeT m的应用实例假定Monad m

我一直在使用Haxl monad(在这里描述:http://www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk),它有一个有趣的特性,即它的Applicative实例的<*>不是与Control.Monad的ap相同。 这是一个关键特性,可以在不阻塞的情况下进行并发计算。 例如,如果hfha是长计算,那么

let hf :: Haxl (a -> b) = ...
    ha :: Haxl a = ...
in do
  f <- hf
  a <- ha
  return (f a)

将按顺序执行,而

hf <*> ha

将并行执行并结合结果。

我希望能够在MaybeT Haxl运行计算,但问题是变形程序包中MaybeT m的Applicative实例使用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 monad,而右边的非括号的<*>m 。)注意上下文是不同的 - 上面的实例假定只有Applicative m ,而变换器中的实例假定Functor m, Monad m

我的主要问题是实际的:我应该怎么做呢? 我应该推出自己的MaybeT monad变压器吗? 有没有办法避开ghc给我的“重复实例声明”的抱怨,如果我试着写上面的话?

我也想知道:目前的设置是否是变形金刚套件中的设计缺陷? 如果不是,为什么不呢?


诀窍是(与monad不同)应用函数是可组合的,所以你不需要( MaybeT )变形函数,比如MaybeT 。 相反,您可以使用Compose将两个应用函数组合在一起:

import Control.Applicative
import Data.Functor.Compose

type HaxlM = Compose Haxl Maybe

-- if you prefer to have a function for constructing values:
haxlM :: Haxl (Maybe a) -> HaxlM a
haxlM = Compose

该构图始终是Applicative的适当实例,并且仅使用其组件的Applicative实例。 例如:

test = getZipList . getCompose
       $ (+) <$> Compose (ZipList [Just 1,  Nothing, Just 3])
             <*> Compose (ZipList [Nothing, Just 20, Just 30])

产生[Nothing,Nothing,Just 33]

链接地址: http://www.djcxy.com/p/68033.html

上一篇: Applicative instance for MaybeT m assumes Monad m

下一篇: Preserve 'randomness' in parallel programs