列表Kleisli to Kleisli列表

gur*_*het 5 scala kleisli scala-cats

我想知道是否有办法把List[Kleisli[Option, Int, Int]]Kleisli[Option, Int, List[Int]].

特别是我有像这样形成的kleisli列表:

def k(a: String) = Kleisli[Option, Int, Int](m => Some(a.length * m))
val kList = List("hi", "hello").map(k)
Run Code Online (Sandbox Code Playgroud)

我所做的是以下内容

Kleisli[Option, Int, List[Int]](m => kList.map(_.run(m)).sequence)
Run Code Online (Sandbox Code Playgroud)

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

有没有更好的办法?

lam*_*sta 6

是的,你可以使用traverse它就是这样.如果您使用cats<= 0.9.0,则可以使用以下代码:

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)
Run Code Online (Sandbox Code Playgroud)

如果您使用的是Scala 2.11.9+,则可以通过添加scalacOptions += "-Ypartial-unification"到您的build.sbt文件traverse中来代替traverseU.另外,从1.0.0版本开始,traverseU并且sequenceU将不再存在.

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

  • 我想补充一下(正如Luka在他的回答中所说的那样)在cat版本1.0.0中你将需要`-Y-partial-unification`标志来使`traverse`编译;) (2认同)