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).