IOr
IOr is a binary operator that applies both left and right to the same input independently and combines
their outputs into a cats.data.Ior. Unlike And (which skips right when left
yields nothing) and Or (which skips right when left succeeds), IOr always
runs both stages and handles all four combinations:
| left \ right | Some |
None |
|---|---|---|
Some |
Ior.Both(l, r) |
Ior.Left(l) |
None |
Ior.Right(r) |
Yield.None |
Statuses from both sides are always merged with combine.
import h8io.stages.*
import h8io.stages.base.*
import h8io.stages.cats.*
object IsPositive extends SAMStage[Int, Int, Nothing] {
override def apply(in: Int): Yield[Int, Int, Nothing] =
if (in > 0) Yield.Some(in, Status.Success, this) else Yield.None(Status.Success, this)
}
object IsEven extends SAMStage[Int, Int, Nothing] {
override def apply(in: Int): Yield[Int, Int, Nothing] =
if (in % 2 == 0) Yield.Some(in, Status.Success, this)
else Yield.None(Status.Success, this)
}
val ior = IOr(IsPositive, IsEven)
// ior: IOr[Int, Int, Int, Nothing] = IOr(
// left = <function1>,
// right = <function1>
// )
ior(4) // both succeed: Ior.Both
// res0: Yield[Int, <none>.<root>.cats.data.Ior[Int, Int], Nothing] = Some(
// out = Both(a = 4, b = 4),
// status = Success,
// evolution = Evolution(left = <function1>, right = <function1>)
// )
ior(3) // left only: Ior.Left
// res1: Yield[Int, <none>.<root>.cats.data.Ior[Int, Int], Nothing] = Some(
// out = Left(a = 3),
// status = Success,
// evolution = Evolution(left = <function1>, right = <function1>)
// )
ior(-2) // right only: Ior.Right
// res2: Yield[Int, <none>.<root>.cats.data.Ior[Int, Int], Nothing] = Some(
// out = Right(b = -2),
// status = Success,
// evolution = Evolution(left = <function1>, right = <function1>)
// )
ior(-3) // neither: Yield.None
// res3: Yield[Int, <none>.<root>.cats.data.Ior[Int, Int], Nothing] = None(
// status = Success,
// evolution = Evolution(left = <function1>, right = <function1>)
// )
Projections
IOr.Left and IOr.Right are projections for cats.data.Ior. Each extracts one side when present,
yielding nothing otherwise. Ior.Both satisfies both projections simultaneously.
import _root_.cats.data.Ior
val leftProj = IOr.Left[Int]
// leftProj: Projection[Ior[Int, ?$2], Int] = <function1>
val rightProj = IOr.Right[Int]
// rightProj: Projection[Ior[?$5, Int], Int] = <function1>
leftProj(Ior.Left(1))
// res4: Yield[Ior[Int, ?$2], Int, Nothing] = Some(
// out = 1,
// status = Success,
// evolution = <function1>
// )
leftProj(Ior.Right(2))
// res5: Yield[Ior[Int, ?$2], Int, Nothing] = None(
// status = Success,
// evolution = <function1>
// )
leftProj(Ior.Both(1, 2))
// res6: Yield[Ior[Int, ?$2], Int, Nothing] = Some(
// out = 1,
// status = Success,
// evolution = <function1>
// )
rightProj(Ior.Left(1))
// res7: Yield[Ior[?$5, Int], Int, Nothing] = None(
// status = Success,
// evolution = <function1>
// )
rightProj(Ior.Right(2))
// res8: Yield[Ior[?$5, Int], Int, Nothing] = Some(
// out = 2,
// status = Success,
// evolution = <function1>
// )
rightProj(Ior.Both(1, 2))
// res9: Yield[Ior[?$5, Int], Int, Nothing] = Some(
// out = 2,
// status = Success,
// evolution = <function1>
// )