我正在重构一个scala http4s应用程序,以消除导致我的应用程序阻塞的一些讨厌的副作用。我用cats.effect.IO替换了.unsafeRunSync。问题如下:
我有两个列表: alreadyAccessible: IO[ListPage]和pages: ListPage我需要过滤掉alreadyAccessible中不包含的页面。然后在结果列表上进行映射,以便在数据库中“授予对这些页面的访问权”。(例如,调用另一个命中数据库并返回IOPage的方法。
val addable: List[Page] = pages.filter(p => !alreadyAccessible.contains(p))
val added: List[Page] = addable.map((p: Page) => {
pageModel.grantAccess(roleLst.head.id, p.id) match {
case Right(p) => p
}
})这接近于我想要的结果;但是,它不起作用,因为filter需要一个返回布尔值的函数,而alreadyAccessible的类型是IO[ListPage],这将阻止您从IO monad中删除任何内容。我知道你不能从IO中删除数据,所以可以转换它:
val added: List[IO[Page]] = for(page <- pages) {
val granted = alreadyAccessible.flatMap((aa: List[Page]) => {
if (!aa.contains(page))
pageModel.grantAccess(roleLst.head.id, page.id) match { case Right(p) => p }
else null
})
} yield granted不幸的是,这不适用于以下错误:
Error:(62, 7) ';' expected but 'yield' found.
} yield granted我想是因为我在某种程度上滥用了for cannot语法,我就是不明白为什么我不能做我正在做的事情。
我知道这样的问题必须有一个直接的解决方案,所以任何意见或建议都是非常感谢的。感谢您花时间阅读这篇文章!
发布于 2020-12-30 14:26:52
granted将成为一个IO[List[Page]]。除非你真的打算像对待值一样对待动作,并对它们进行重新排序/过滤等,否则将IO放在其他任何东西中并没有什么特别的意义。
val granted: IO[List[Page]] = for {你是如何计算的?那么,第一步是执行alreadyAccessible来获得实际的列表。事实上,alreadyAccessible的名字是错误的。它不是可访问页面的列表;它是一个获取可访问页面列表的操作。我建议您将其重命名为getAlreadyAccessible。
alreadyAccessible <- getAlreadyAccessible然后用它过滤pages
val required = pages.filterNot(alreadyAccessible.contains)现在,我不能破译你对这些页面做了什么。我假设你有某种grantAccess: Page => IO[Page]函数。如果你在required上映射这个函数,你会得到一个List[IO[Page]],这是不可取的。相反,我们应该使用grantAccess执行traverse,这将生成一个执行每个IO[Page]的IO[List[Page]],然后将所有结果组装到一个List[Page]中。
granted <- required.traverse(grantAccess)我们就完事了
} yield grantedhttps://stackoverflow.com/questions/65501020
复制相似问题