在Scala / Scalaz中链接Either
或\/
类型相当容易,以便从左侧“失败”值中恢复。
如何为函数(T1, T2) => Future[A \/ B]
获取相同的行为?
我已经能够在两个不同的方向上解决这个问题,但无法将解决方案结合起来。
通过简单地将Scalaz的Future[A \/ B]
用作EitherT
和type FutureEither[A, B] = EitherT[Future, A, B]
的monad实例来链接Future
很容易。
我已经能够使用(T1, T2) => A \/ B
链接EitherT
类型:
implicit def wrapTransform[T1, T2, A, B](f: Function2[T1, T2, A \/ B]) = EitherT[({ type λ[α] = Function2[T1, T2, α] })#λ, A, B](f)
implicit def unwrapTransform[T1, T2, A, B](e: EitherT[({ type λ[α] = Function2[T1, T2, α] })#λ, A, B]): Function2[T1, T2, A \/ B] = e.run
// some dummy functions
def times2(fail: Boolean, v: Int): String \/ Int = if (fail) "times2:FAILED".left else (v * 2).right
def fail(v1: Boolean, v: Int): String \/ Int = "fail:FAILED".left
def alwaysPlus1(ignore: Boolean, v: Int): String \/ Int = (v + 1).right
val times2_times2 = (times2 _) orElse (times2 _)
val alwaysPlus1_times2 = (alwaysPlus1 _) orElse (times2 _)
Console println times2_times2(false, 10) // prints '\/-(20)'
Console println times2_times2(true, 10) // prints '-\/(times2:FAILED)'
Console println alwaysPlus1_times2(false, 10) // prints '\/-(11)''
Console println alwaysPlus1_times2(true, 10) // prints '\/-(11)'
如何编写适用于(T1, T2) => Future[A \/ B]
类型的两级嵌套的转换器?
我对函数式编程的了解仍在进行中,所以我为措辞不当和术语用法道歉。
答案 0 :(得分:0)
如果你有例如Option
代替Future
,您可以在堆栈中添加图层:
def wrap[T1, T2, A, B](f: (T1, T2) => Option[A \/ B]) = EitherT[
({ type L1[a] = OptionT[
({ type L2[b] = (T1, T2) => b })#L2, a
] })#L1, A, B
](OptionT[({ type L2[b] = (T1, T2) => b })#L2, A \/ B](f))
这是一团糟,但你可以相当机械地填写类型,因为你只是从内到外 - 例如。我们的(T1, T2) => Option[A \/ _]
变为EitherT[OptionT[(T1, T2) => _, _], A, _]
问题在于,如果您想使用Future
执行此操作,则需要FutureT
,并且一致意见是,因为它是not possible to write FutureT
without blocking,it's better not to provide it。