Consider this code:
def f1(a: Int, b: Int) = a + b
def f2(a: Option[Int], b: Option[Int]): Int = (a, b) match {
case (Some(x), Some(y)) => x + y
case _ => throw new IllegalArgumentException
}
println(f1(10, 20))
println(f2(Some(10), Some(20)))
I heard you can "lift" f1 to be like f2. As a beginner I have the following question:
What is lifting and why it used? In terms of implementation, how can I "lift" f1?
Any explanation is greatly appreciated as it is a bit tricky to find why I would "lift" something
Why: when you have a function with signature like f1
and want to "call it" on Option[Int]
s (or List[Int]
s, etc)
How: you could write it directly:
def lift2option[A, B, C](f: (A, B) => C): (Option[A], Option[B]) => Option[C] = ???
I'm leaving it undefined because you should try writing it yourself; your definition of f2
should be a good starting point. Note that I made it return Option[Int]
instead of Int
. Later I can edit and give the answer if you want.
And then instead of defining f2
as separate function, you do:
val f2 = lift2option(f1 _)
println(f2(Some(10), Some(20)))
Of course, the point is that now for any function with a signature like f1
you can get an f2
equivalent.
It can be further generalized to work not only for Option
, but you'll want to look into that later.