如何将Seq [Reader [E,A]])转换为Reader [E,Seq [A]]

Yan*_*san 3 monads scala scalaz

这是我的实际解决方案

  private def transpose[E, A](readers : Seq[Reader[E, A]]) : Reader[E, Seq[A]] =
    Reader { e: E => readers.map { r => r(e) } }
Run Code Online (Sandbox Code Playgroud)

scalaz是否有更简单的解决方案(可能使用现有的组合器)?

Tra*_*own 5

这个操作基本上是sequence:

import scalaz.Reader, scalaz.std.list._, scalaz.syntax.traverse._

def transpose[E, A](readers: List[Reader[E, A]]): Reader[E, List[A]] =
  readers.sequenceU
Run Code Online (Sandbox Code Playgroud)

一般来说,如果M有一个Traverse实例,N是一个单子,你可以转换M[N[A]]成一个N[M[A]]以这种方式(见我的答案在这里一些额外的细节).

请注意,sequence不会工作Seq,因为Scalaz不提供Traverse例如Seq(虽然它的List,Vector等等).你可以写自己的,但我建议你不要这样做.

(作为一个脚注,这里U的结尾sequenceU只是帮助Scala类型推断的黑客行为的一部分 - 请参阅我的博客文章,了解一些背景信息.)