Вы бы использовали монаду состояния, параметризованную другой монадой, представляющей завершение.
Обычно такие параметризованные монады называются монадными преобразователями .В этом конкретном случае вы бы использовали монадный преобразователь StateT
.По модулю некоторых деталей реализации, StateT
эквивалентно
type StateT[F[_], S, A] = S => F[(S, A)]
Теперь вы можете выбрать F
равным Option
, что означает немедленное завершение.
import scalaz.StateT
import scalaz.std.option._
object StateTest {
type Stack = List[Int]
def main(args: Array[String]) = {
println(transition.run(List(1, 2, 3, 4))) // Some((List(4), 3))
println(transition.run(List(1, 2))) // None
}
def transition: StateT[Option, Stack, Int] = for {
_ <- pop
_ <- pop
a <- pop
} yield a
def pop: StateT[Option, Stack, Int] = StateT {
case x::xs => Some((xs, x))
case Nil => None
}
}
Если вы хотитевернуть некоторое значение типа B
даже в случае досрочного завершения, вы можете использовать Either[B, ?]
вместо Option
для параметризации StateT
:
type ErrorOr[A] = Either[String, A]
def pop1: StateT[ErrorOr, Stack, Int] = StateT {
case x::xs => Right((xs, x))
case Nil => Left("Cannot pop from an empty stack.")
}