首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MaybeT m的应用实例假定Monad m

MaybeT m的应用实例假定Monad m
EN

Stack Overflow用户
提问于 2014-03-31 05:48:58
回答 1查看 517关注 0票数 13

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

代码语言:javascript
复制
let hf :: Haxl (a -> b) = ...
    ha :: Haxl a = ...
in do
  f <- hf
  a <- ha
  return (f a)

将按顺序执行它们,而

代码语言:javascript
复制
hf <*> ha

将并行执行它们,然后合并结果。

我希望能够在MaybeT Haxl中运行计算,但问题是transformers包中的MaybeT m应用实例使用了一元绑定:

代码语言:javascript
复制
instance (Functor m, Monad m) => Applicative (MaybeT m) where
    pure = return
    (<*>) = ap

其中ap = liftM2 id来自Control.Monad。这使得

代码语言:javascript
复制
let hmf :: MaybeT Haxl (a -> b) = ...
    hma :: MaybeT Haxl a = ...
in hmf <*> hma

按顺序运行。看起来一个更好的实例更像是

代码语言:javascript
复制
instance (Applicative m) => Applicative (MaybeT m) where
    pure = MaybeT . pure . Just
    MaybeT f <*> MaybeT x = MaybeT $ (<*>) <$> f <*> x

(在这里,右侧的(<*>)用于Maybe monad,而右侧的非括号<*>用于m。)注意,上下文是不同的--上面的实例只假设Applicative m,而transformers中的实例假设Functor m, Monad m

我的主要问题是实用的:我应该为此做些什么?我应该使用自己的MaybeT monad转换器吗?如果我尝试写上面的代码,有没有办法绕过ghc给我的“重复实例声明”的抱怨?

我还想知道:当前的设置是不是transformers包中的设计缺陷?若否,原因为何?

EN

回答 1

Stack Overflow用户

发布于 2014-03-31 13:34:52

诀窍是(与单体不同)应用函数式是可组合的,因此您不需要像MaybeT这样的(应用型)转换器。相反,您可以使用Compose将两个应用函数器组合在一起:

代码语言:javascript
复制
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实例。例如:

代码语言:javascript
复制
test = getZipList . getCompose
       $ (+) <$> Compose (ZipList [Just 1,  Nothing, Just 3])
             <*> Compose (ZipList [Nothing, Just 20, Just 30])

生成[Nothing,Nothing,Just 33]

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22750315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档