加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何使用Applicative进行并发?

发布时间:2020-12-16 18:39:09 所属栏目:安全 来源:网络整理
导读:这是我之前的 question的后续行动.我从 Haxl复制了下面的例子 假设我从博客服务器获取数据以呈现博客页面,其中包含最近的帖子,热门帖子和帖子主题. 我有以下数据提取API: val getRecent : Server = Seq[Post] = ...val getPopular : Server = Seq[Post] = .
这是我之前的 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?
>如何实现Fetch作为应用程序而不是Monad?

解决方法

How to implement getPageData assuming Fetch[A] is an Applicative ?

我们需要做的就是删除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)

但这是否具有预期的效果取决于第二个问题!

How to implement Fetch as an Applicative but not a Monad ?

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读