То, что вы описываете как Преобразование (так что функция A => F [B] ) часто называют стрелками Клейсли.
Кошки Библиотека имеет тип данных, что облегчает работу с этими функциями. Например, у него есть метод andThen , который разрешает составление этих функций:
import cats.data.Kleisli
import cats.implicits._
val t1: Transformation[Int] = t => Future.successful(t + t)
val t2: Transformation[Int] = _ => Future.failed(new NoSuchElementException)
Kleisli(t1).andThen(Kleisli(t2))
Единственная проблема заключается в том, что одно из ваших преобразований может вернуть неудачное будущее, что приведет к короткому замыканию. -контур всей цепи. Мы можем исправить это с помощью recoverWith .
Итак, в конечном итоге translationChain может выглядеть так:
def transformationChain[T](chain: Seq[Transformation[T]]): Transformation[T] =
t =>
chain
//wrap the function in Kleisli and then use replace failed futures with succeeded
//future, that are passing value over
.map(Kleisli(_).recoverWith {
case _ => Kleisli(x => Future.successful(x))
})
.reduce(_ andThen _) //combine all elements with andThen
.apply(t)
Работает нормально для случаев 1 и 3, но не работает в случае 2, так как он просто вернет переданное значение.
println(Await.result(tc(2), 5.seconds)) // 16
println(Await.result(tc3(2), 5.seconds)) // 4
println(Await.result(tc2(2), 5.seconds)) // 2