"scalaz-core"%"7.2.14"
StateTモナドの構成でfailover
の何らかの動作を作成しようとしています。StateT [どちらか] Scalazのフェイルオーバーあり
EitherT周りStateTモナドラップは、このように、それはモナド変換子です:
type Error = String
type ErrOrT[T] = Error \/ T
type State[T] = StateT[ErrOrT, String, T]
これらのタイプのすべてには素晴らしい作品 - 私はEither
プラスState
の力を活用することができます。私はtryWithFailover
法のようなものを作りたいまた
def func1: State[Int] = ???
def func2: State[Int] = ???
def func3: State[Int] = ???
val stateMonad = for {
res1 <- func1
res2 <- func2
res3 <- func3
} yield res3
:私は、エラーの場合には、短絡を持っており、1つのモナド組成物中に、私の国をスタックすることができます。これは、元State[T]
モナドを返すか、インナーEitherT
の場合にState[T]
モナドをフォールバック左含まれています
def tryWithFailover[T](run: State[T])(failover: Error => State[T]): State[T] = ???
だから、結果としてチェーンは次のようになります。
val stateMonad = for {
res1 <- func1
res2 <- tryWithFailover(func2)(err => failover)
res3 <- func3
} yield res3
failover
はそれができないのと同じ値だった場合問題。私はmapT/mapK
のメソッドを使用して内部モナドにアクセスし、その結果が左か右かをチェックすることができます。左の場合は、fallback
の値を持つ内部モナドを作り直すことができます。しかし、それは価値ではありません、それはモナドそのものなので、私はflatMapT
のようなものが必要です。
私は何かが恋しくなっていますか?フェールオーバーユーティリティ機能は私をたくさん助け、明示的にrun
コールと真ん中のチェーンを壊したくない。
UPD:
値と上記に言及フェイルオーバーは、次のように次のようになります。
def tryWithFailover[T](run: State[T])(failover: Error => T): State[T] = {
for {
lockedState <- State(st => (st, st))
result <- run.mapT[ErrOrT, T, String] {
case [email protected] \/-(_) => ok
case -\/(error) => \/-((lockedState, failover(error)))
}
} yield result
}
UPD2:
悪い実装全体のモナドを破ります真ん中にrun
とチェーン:私はアプローチを述べたという結論に達しましたいくつかの考慮後
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 [email protected] \/-(_) => ok
case -\/(error) => failover(error).run(lockedState)
}
} yield result
}