如何使用scalaz序列将T [G [A]]变换为G [T [A]]

时间:2014-10-29 00:21:43

标签: scala scalaz scalaz7

我有这个代码使用scalaz序列将List [Future [Int]]转换为Future [List [Int]]。

import scalaz.concurrent.Future

val t = List(Future.now(1), Future.now(2), Future.now(3)) //List[Future[Int]]
val r = t.sequence //Future[List[Int]]

因为我使用的是来自scalaz的Future,所以它可能有隐含的解决方案来为我做魔术,我只是想知道类型类是否是自定义类没有像Future这样的预定义,我怎么能定义隐式分辨率来实现同样的结果

case class Foo(x: Int)

val t = List(Foo(1), Foo(2), Foo(3)) //List[Foo[Int]]

val r = t.sequence //Foo[List[Int]]

非常感谢提前

1 个答案:

答案 0 :(得分:3)

您需要创建一个隐式范围内的Applicative[Foo](或Monad[Foo])。

您要求的内容将无法正常运行,因为Foo未被普遍量化(因此r的预期类型与Foo[List[Int]]无关,因为Foo {1}}不接受类型参数。

让我们以不同方式定义Foo

case class Foo[A](a: A)

object Foo {
  implicit val fooApplicative = new Applicative[Foo] {
      override def point[A](a: => A) = Foo(a)
      override def ap[A,B](fa: => Foo[A])(f: => Foo[A=>B]): Foo[B] = Foo(f.a(fa.a))
  } 
}

现在,如果我们确保隐含在范围内,我们可以按顺序进行:

scala> val t = List(Foo(1), Foo(2), Foo(3)) 
t: List[Foo[Int]] = List(Foo(1), Foo(2), Foo(3))

scala> t.sequence
res0: Foo[List[Int]] = Foo(List(1, 2, 3))