scala – 如何使用Applicative进行并发?
这是我之前的
question的后续行动.我从
Haxl复制了下面的例子
假设我从博客服务器获取数据以呈现博客页面,其中包含最近的帖子,热门帖子和帖子主题. 我有以下数据提取API: val getRecent : Server => Seq[Post] = ... val getPopular : Server => Seq[Post] = ... val getTopics : Server => Seq[Topic] = ... 现在我需要编写它们来实现一个新函数getPageData val getPageData: Server => (Seq[Post],Seq[Post],Seq[Topic]) Haxl建议使用新的monad Fetch使API可组合. val getRecent : Fetch[Seq[Posts]] = ... val getPopular : Fetch[Seq[Posts]] = ... val getTopics : Fetch[Seq[Topic]] = ... 现在我可以定义我的getPageData:使用monadic组合获取[A] val getPageData = for { recent <- getRecent popular <- getPopular topics <- getTopics } yield (recent,popular,topics) 但它不会同时运行getRecent,getPopular和getTopics. Haxl建议使用施用组合物< *>.组成“并发”函数(即可以并发运行的函数).所以我的问题是: >假设Fetch [A]是一个应用程序,如何实现getPageData? 解决方法
我们需要做的就是删除monadic bind>> =以支持applicative< *>.而不是 val getPageData = for { recent <- getRecent popular <- getPopular topics <- getTopics } yield (recent,topics) 我们会写类似的东西(在Haskell语法中;对不起,我不能把Scala放在我的头顶): getPageData = makeTriple <$> getRecent <*> getPopular <*> getTopics where makeTriple x y z = (x,y,z) 但这是否具有预期的效果取决于第二个问题!
monadic和应用测序之间的关键区别在于monadic和monadic可以依赖于monadic值内的值,而应用< *>.不能.请注意getPageData上面的monadic表达式如何在到达getTopics之前绑定最近和流行的名称.这些名称可能已被用于更改表达式的结构,例如通过获取其他数据源以防最近为空.但是使用应用表达式,getRecent和getPopular的结果不是表达式本身结构中的因素.这个属性允许我们同时触发applicative表达式中的每个术语,因为我们静态地知道表达式的结构. 因此,使用上面的观察,以及显然Fetch数据类型的特定形状,我们可以为< *>提出合适的定义.我认为以下说明了一般的想法: data Fetch a = Fetch { runFetch :: IO a } fetchF <*> fetchX = Fetch $do -- Fire off both IOs concurrently. resultF <- async $runFetch fetchF resultX <- async $runFetch fetchX -- Wait for both results to be ready. f <- wait resultF x <- wait resultX return $f x 为了比较,假设我们尝试使用并发评估进行monadic绑定: fetchF >>= fetchK = Fetch $do resultF <- async $runFetch fetchF -- Oh no,we need resultF in order to produce the next -- Fetch value! We just have to wait... f <- wait resultF fetchX <- async $runFetch (fetchK f) x <- wait $runFetch fetchX return $f x (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |