I am not familiar with the Flow API.
The term “lifting” comes from category theory. In programming languages such as Haskell or Scala, a lift
function takes a function A => B
, and somehow performs magic so that the lifted function F[A] => F[B]
can be applied to a functor or monad F[A]
.
A concrete example using Scala's Seq
container: Assume we have a function def double(x: Int): Int = 2 * x
, and a sequence val xs = Seq(1, 2, 3)
. We cannot double(xs)
due to incompatible types. But if we obtain a val doubleSeq = liftToSeq(double)
, we can do doubleSeq(xs)
, which evaluates to Seq(2, 4, 6)
. Here, liftToSeq
can be implemented as
def liftToSeq[A, B](f: A => B): (Seq[A] => Seq[B]) =
(seq: Seq[A]) => seq.map(f)
The Seq(…)
constructor can also be seen as a lifting operation, which lifts the values 1, 2, 3
into a Seq
instance, thus allowing us to use list abstractions for these values.
Monads allow us to encapsulate the inner workings of some type by offering a watertight but composable interface. Using a lifted representation can make it easier to reason about a computation. Using such abstractions also means that we lose knowledge of the abstracted-away specifics, but those are needed for providing an efficient implementation under the hood (finding a suitable execution representation).