[英]StateT[Either] with failover in Scalaz
I'm trying to create some kind of failover
behaviour in a composition of "scalaz-core"%"7.2.14"
StateT monads. 我试图在
"scalaz-core"%"7.2.14"
StateT monads的组合中创建某种failover
行为。
The StateT monad wraps around EitherT thus it's a monad transformer: StateT monad绕过EitherT,因此它是monad变换器:
type Error = String
type ErrOrT[T] = Error \/ T
type State[T] = StateT[ErrOrT, String, T]
With these types everything works great - I can leverage the power of Either
plus State
. 一切都很好 - 我可以利用
Either
plus State
的力量。 I have short-circuit in case of error and can stack my States in one monadic composition: 如果出现错误,我会发生短路,并且可以将我的状态叠加在一个monadic组合中:
def func1: State[Int] = ???
def func2: State[Int] = ???
def func3: State[Int] = ???
val stateMonad = for {
res1 <- func1
res2 <- func2
res3 <- func3
} yield res3
In addition I want to create something like tryWithFailover
method. 另外我想创建类似
tryWithFailover
方法的东西。 It returns original State[T]
monad or fallback State[T]
monad in case of inner EitherT
contains left: 在内部
EitherT
包含左边的情况下,它返回原始State[T]
monad或fallback State[T]
monad:
def tryWithFailover[T](run: State[T])(failover: Error => State[T]): State[T] = ???
So the resulting chain would be: 因此产生的链将是:
val stateMonad = for {
res1 <- func1
res2 <- tryWithFailover(func2)(err => failover)
res3 <- func3
} yield res3
If the failover
was just a value it would not be a problem. 如果
failover
只是一个值,那就不会有问题了。 I can use mapT/mapK
methods which have an access to inner monad and thus able to check whether the result left or right. 我可以使用
mapT/mapK
方法,这些方法可以访问内部monad,从而可以检查结果是左还是右。 In case of left I can recreate inner monad with fallback
value. 如果离开,我可以重新创建具有
fallback
值的内部monad。 But it's not a value, it's a monad itself and I need something like flatMapT
. 但它不是一个价值,它本身就是一个单子,我需要像
flatMapT
这样的flatMapT
。
Do I miss something, any thought on how it might be done? 我是否会错过任何关于它如何做的想法? Failover util function will help me a lot, don't want to break the chain in the middle with explicit
run
call. 故障转移util函数对我有很大帮助,不希望在显式
run
调用中打破中间链。
UPD: UPD:
Abovementioned failover with value might be like this: 上述带有值的故障转移可能如下所示:
def tryWithFailover[T](run: State[T])(failover: Error => T): State[T] = {
for {
lockedState <- State(st => (st, st))
result <- run.mapT[ErrOrT, T, String] {
case ok@ \/-(_) => ok
case -\/(error) => \/-((lockedState, failover(error)))
}
} yield result
}
UPD2: UPD2:
Bad implementation which breaks overall monadic chain with run
in the middle: 在中间
run
打破整体monadic链的糟糕实现:
def tryWithFailover[T](run: State[T])(failover: Error => State[T]): State[T] = {
for {
lockedState <- State(st => (st, st))
result <- run.mapT[ErrOrT, T, String] {
case ok@ \/-(_) => ok
case -\/(error) => failover(error).run(lockedState)
}
} yield result
}
After some considerations I came to the conclusion that mentioned approach is not bad: 经过一些考虑,我得出结论,提到的方法并不坏:
def tryWithFailover[T](run: State[T])(failover: Error => State[T]): State[T] = {
for {
lockedState <- State(st => (st, st))
result <- run.mapT[ErrOrT, T, String] {
case ok@DRight(_) => ok
case DLeft(error) => failover(error).run(lockedState)
}
} yield result
}
May be someday somebody will correct my answer. 可能有一天有人会纠正我的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.