首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >清单中的Kleisli到Kleisli

清单中的Kleisli到Kleisli
EN

Stack Overflow用户
提问于 2017-10-14 00:00:19
回答 3查看 347关注 0票数 5

我想知道是否有办法将List[Kleisli[Option, Int, Int]]转换为Kleisli[Option, Int, List[Int]]

特别是,我有这样的kleisli清单:

代码语言:javascript
复制
def k(a: String) = Kleisli[Option, Int, Int](m => Some(a.length * m))
val kList = List("hi", "hello").map(k)

我要做的是

代码语言:javascript
复制
Kleisli[Option, Int, List[Int]](m => kList.map(_.run(m)).sequence)

这是非常混乱,没有表现力,需要大量的手工工作。

有更好的办法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-10-14 00:58:30

是的,您可以使用traverse来实现这一点。如果使用的是cats <= 0.9.0,可以使用以下代码:

代码语言:javascript
复制
import cats.data._
import cats.instances.list._
import cats.instances.option._
import cats.syntax.traverse._

// ...
def k(a: String) = Kleisli[Option, Int, Int](m => Some(a.length * m))
val result: Kleisli[Option, Int, List[Int] = List("hi", "hello").traverseU(k)

如果您使用Scala 2.11.9+,通过将scalacOptions += "-Ypartial-unification"添加到build.sbt文件中,您只需使用traverse代替traverseU即可。此外,从1.0.0版本开始,traverseUsequenceU将不再存在。

注意,如果使用Scala < 2.11.9但>= 2.10.6,则仍然可以通过将这个插件添加到构建中来启用部分统一。

票数 6
EN

Stack Overflow用户

发布于 2017-10-14 01:08:40

最简单的方法就是启用partial-unification并使用traverse

代码语言:javascript
复制
import cats.implicits._

List("hi", "hello").traverse(k)

这与在sequence上运行kList是一样的,因为traverse等同于map,然后是sequence

启用partial-unification的最简单方法是添加sbt-partial-unification 插件

如果您使用的是Scala 2.11.9或更高版本,也可以简单地添加编译器标志:

代码语言:javascript
复制
scalacOptions += "-Ypartial-unification"

我们cats团队强烈鼓励您在使用猫时始终戴上此标志,因为它使一切变得简单多了。

票数 4
EN

Stack Overflow用户

发布于 2017-10-14 03:19:26

使用TraverseOps.sequence,我们可以将List[A[B]]转换为A[List[B]],其中

代码语言:javascript
复制
A = ({type λ[α] = Kleisli[Option, Int, α]})#λ
B = Int

所以答案是:

代码语言:javascript
复制
def transform(x: List[Kleisli[Option, Int, Int]]) =
  x.sequence[({type λ[α] = Kleisli[Option, Int, α]})#λ, Int]

以下代码是完整的解决方案:

代码语言:javascript
复制
import scalaz._
import Scalaz._
import scalaz.Kleisli._

def transform(x: List[Kleisli[Option, Int, Int]]) = x.sequence[({type λ[α] = Kleisli[Option, Int, α]})#λ, Int]

def k(a: String) = Kleisli[Option, Int, Int](m => Some(a.length * m))
val kList = List("hi", "hello").map(k)
val res = transform(kList)
res.run(10)

https://scastie.scala-lang.org/2uZvWWb1ScOHNA55QOcWQA

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

https://stackoverflow.com/questions/46739449

复制
相关文章

相似问题

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