简体   繁体   English

MaybeT m的应用实例假设Monad m

[英]Applicative instance for MaybeT m assumes Monad m

I've been using the Haxl monad (described here: http://www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk ), which has the interesting feature that <*> for its Applicative instance isn't the same as ap from Control.Monad. 我一直在使用Haxl monad(在此描述: http//www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk ),其中有一个有趣的特性,即其Applicative实例的<*>不是与Control.Monad中的ap相同。 This is a key feature that allows it to do concurrent computations without blocking. 这是一个关键功能,允许它在不阻塞的情况下进行并发计算。 For example, if hf and ha are long computations, then 例如,如果hfha是长计算,那么

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

will do them sequentially, while 将按顺序执行它们

hf <*> ha

will do them in parallel and then combine the results. 将并行完成它们然后结合结果。

I would like to be able to run computations in MaybeT Haxl , but the problem is that the Applicative instance for MaybeT m in the transformers package uses monadic bind: 我希望能够在MaybeT Haxl运行计算,但问题是变换器包中的MaybeT m的Applicative实例使用MaybeT m绑定:

instance (Functor m, Monad m) => Applicative (MaybeT m) where
    pure = return
    (<*>) = ap

Where ap = liftM2 id is from Control.Monad . 其中ap = liftM2 id来自Control.Monad This makes 这使得

let hmf :: MaybeT Haxl (a -> b) = ...
    hma :: MaybeT Haxl a = ...
in hmf <*> hma

run sequentially. 顺序运行。 It seems like a better instance would be more like 似乎更好的实例会更像

instance (Applicative m) => Applicative (MaybeT m) where
    pure = MaybeT . pure . Just
    MaybeT f <*> MaybeT x = MaybeT $ (<*>) <$> f <*> x

(Here, (<*>) on the right-hand side is for the Maybe monad, while the non-parenthesized <*> on the right-hand side is for m .) Note that the context is different -- the above instance assumes only Applicative m , while the instance in transformers assumes Functor m, Monad m . (这里,右侧的(<*>)Maybe monad,而右侧的非括号<*>m 。)注意上下文不同 - 上面的例子假设只有Applicative m ,而变换器中的实例则假定是Functor m, Monad m

My main question is practical: what should I do about this? 我的主要问题是实际问题:我该怎么做? Should I roll my own MaybeT monad transformer? 我应该推出自己的MaybeT monad变压器吗? Is there some way to get around the "Duplicate instance declarations" complaint that ghc gives me if I try to write the above? 有没有办法解决ghc给我的“重复实例声明”投诉,如果我尝试编写上述内容?

I'd also like to know: is the current setup a design flaw in the transformers package? 我也想知道:目前的设置是变压器封装中的设计缺陷吗? If not, why not? 如果没有,为什么不呢?

The trick is that (unlike monads) applicative functors are composable, so you don't need (applicative) transformers such as MaybeT . 诀窍是(与monads不同)applicative functor是可组合的,因此你不需要(applicative)变换器,例如MaybeT Instead, you can use Compose to combine two applicative functors together: 相反,您可以使用Compose将两个applicative functor组合在一起:

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

The composition is always a proper instance of Applicative and use only the Applicative instance of their components. 组合始终是Applicative的正确实例,并且仅使用其组件的Applicative实例。 For example: 例如:

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

produces [Nothing,Nothing,Just 33] . 产生[Nothing,Nothing,Just 33]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM