简体   繁体   English

StateT [要么]在Scalaz中进行故障转移

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM