Scala 列表[OptionT[Future,Int]]至OptionT[Future,List[A]]

Scala 列表[OptionT[Future,Int]]至OptionT[Future,List[A]],scala,scalaz,monad-transformers,Scala,Scalaz,Monad Transformers,我正在使用异步计算来检索元素,构建一个Int的列表: (1 to n).map(anAsyncThingy).toList 其中anAsyncThingy返回OptionT[Future,Int] 因此,结果的类型为List[OptionT[Future,Int] 我现在想要的是一个选项[未来,列表[A]] 这是我迄今为止最好的尝试(我将添加一些存根,以便它可以在REPL中运行) 上面的工作与预期的一样,但是我觉得使用适当的scalaz构造有很大的改进空间,而不是从monad Transfor

我正在使用异步计算来检索元素,构建一个
Int
列表:

(1 to n).map(anAsyncThingy).toList
其中
anAsyncThingy
返回
OptionT[Future,Int]

因此,结果的类型为
List[OptionT[Future,Int]

我现在想要的是一个
选项[未来,列表[A]]

这是我迄今为止最好的尝试(我将添加一些存根,以便它可以在REPL中运行)

上面的工作与预期的一样,但是我觉得使用适当的scalaz构造有很大的改进空间,而不是从monad Transformer跳进跳出


我怎样才能以更直接的方式获得相同的结果?

经过一些实验,我自己找到了答案:

val res = (1 to 3).map(anAsyncThingy).toList.sequenceU
res.map(println) // List(1, 2, 3)
对斯卡拉兹来说太好了

顺便说一句,
sequenceU
是需要的,而不是
sequence
,因为scala不够聪明,无法判断何时有

OptionT[M, A]
如果您修复了一个类型参数(
M
Future

它的形状为
M[\u]

编译器一直认为它有一个
M[\uu,\u]
形状,除非有勺子(带有讨厌的lambda类型)

这里是scalaz的
sequenceU
的切入点,它使用
Unapply
解决了这个问题。更多关于这个问题

更新 根据phadej的评论,
顺序∘ 地图≡ traverse
,因此这可以通过
traverseU
变得更加简洁:

(1 to 3).toList.traverseU(anAsyncThingy)

当然,
sequence
vs
sequenceU
的相同概念也适用于
traverse
vs
traverseU

作为旁注:
sequence∘ 地图≡ 遍历
,所以我宁愿写:
(1到3)。toList traverseU anAsyncThingy
OptionT[Future, A]
(1 to 3).toList.traverseU(anAsyncThingy)