Unpack the meaning of this lift function - scala

I am not sure how the following function works:
def lift[A, B](f: A => B): Option[A] => Option[B] = _ map f
I know it transforms a function which takes a value of type A and returns a value of type B into a function which takes a value of type Option[A] and returns an Option[B]. But I am stuck on what the underscore is doing and how the map works. Can someone expand the function definition?

def lift[A, B](f: A => B): Option[A] => Option[B] = _ map f
it exapnds to
def lift[A, B](f: A => B): Option[A] => Option[B] = x => x map f
(this is how underscore works in this context)
The return type is annotated to be Option[A] => Option[B]. Thanks to this compiler will know that x is of type Option[A]. We can say it explicitly, expanding it further
def lift[A, B](f: A => B): Option[A] => Option[B] = (x: Option[A]) => x map f
So, the returned function takes an Option[A] and maps it using f. Option.map takes parameter that is a function A => B so everything is correct.
Note that since I annotated the type that function takes as a parameter you can now omit the type of lift method like this
def lift[A, B](f: A => B) = (x: Option[A]) => x map f
All the snippets I wrote in this post are equivalent.

_ map f in this case returns a function that takes an Option[A] and returns an Option[B].
The _ in this case is a shortcut to build and return a function by specifying its argument position.
So here, the position of the Option[A] argument.
Whenever this returned function will be further called, it would execute:
thePassedOptionA map f

Related

Making a partial function complete

Is there a standard way to complete a partial function PartialFunction[A, B]? Something like this:
completePartialFunction(pf: PartialFunction[A, B], z: B): A => B
or
completePartialFunction2(pf: PartialFunction[A, B], f: A => B): A => B
Yes, it's actually very simple:
def complete[A, B](pf: PartialFunction[A, B])(f: A => B): A => B =
pf.applyOrElse(_, f)
You can use lift method on PartialFunction, that returns Option[B]. So when the function is not defined for the input, None is returned. You can find more in the scaladocs.
Other solution that comes to my mind is when you're using cats or scalaz. You can then check whether the function is defined for the argument and when not, return empty from the Monoid[B] that you should pass (probably implicitly) to completePartialFunction.
If I understand the question, you want to use f() to supplement pf() so that all possible values of type A are covered.
def completePartialFunction2[A,B](pf : PartialFunction[A,B]
,f : A => B): A => B =
(a:A) => if (pf.isDefinedAt(a)) pf(a) else f(a)
Another simple version:
def completePartialFunction[A, B](pf: PartialFunction[A, B], f: A => B): A => B
= pf orElse { case a: A => f(a) }

Calling map with flatMap(for Option data type) but the types don't match in scala

I am walking through the 'Functional Programming in Scala' exercises and in chapter 4 there is this one piece of code about the Option class that I think I am having troubles to understand.
I am asked to implement flatMap. I know that Map is meant to transform an A to a B, and then wrap it in an Option. So what even is the purpose of flatMap? If I recall correctly, flatMap implemented in lists is meant to take a function that would transform A to a List of a B. A => List[B]. In principle, I imagine that applies here as well. That Option is just a list with one element and I am to give it a function that is meant to take an A and wrap it inside of an Option.
I don't know how I would implement flatMap using Map. The apparent implementation is as simple as:
def flatMap(f: A => Option[B]): Option[B] = map(f) getOrElse None
Why does this implementation work? f does not have the type signature of A=>B, yet it calls map just fine with this signature. Obviously calling getOrElse(None) is what makes it work, because if I take that out the implementation starts to complain. But I don't understand why the scala interpreter is not complaining here. We know that f returns an Option[B]. Is That returned Option calling getOrElse, which is then unwrapping its value so it can have the right type signature? If this is the case, are there other ways to write this that would be more obvious as to why it would work?
def flatMap[B](f: A => Option[B]): Option[B] =
map((a)=> f(a).getOrElse(None)) // doesn't work
Unfortunately this book does not really provide an in depth introduction to scala so I am not sure if this is syntax(pretty sure its syntactical) or logic that I am not understanding.
import scala.{Option => _, Some => _, Either => _, _} // hide std library `Option`, `Some` and `Either`, since we are writing our own in this chapter
sealed trait Option[+A] {
def map[B](f: A => B): Option[B] = this match {
case Some(a) => Some(f(a))
case None => None
}
def getOrElse[B>:A](default: => B): B = this match {
case None => default
case Some(b) => b
}
def flatMap[B](f: A => Option[B]): Option[B] =
map(f) getOrElse(None)
def orElse[B>:A](ob: => Option[B]): Option[B] = ???
def filter(f: A => Boolean): Option[A] = ???
}
case class Some[+A](get: A) extends Option[A]
case object None extends Option[Nothing]
object Option {
def mean(xs: Seq[Double]): Option[Double] =
if (xs.isEmpty) None
else Some(xs.sum / xs.length)
def variance(xs: Seq[Double]): Option[Double] = ???
def map2[A,B,C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] = ???
def sequence[A](a: List[Option[A]]): Option[List[A]] = ???
def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] = ???
}
Your intuition as to the meaning of flatMap is perfectly correct. I believe your confusion regarding the implementation stems from the fact that B is a type parameter defined per method, and as such, it doesn't have to be have the same value when one method calls the other.
To show this, let's simply give the type parameters of these methods different names:
def map[B](f: A => B): Option[B] = this match {
case Some(a) => Some(f(a))
case None => None
}
def getOrElse[C>:A](default: => C): C = this match {
case None => default
case Some(b) => b
}
def flatMap[D](f: A => Option[D]): Option[D] = {
map(f) getOrElse None
}
Now:
flatMap has a type parameter D, which can be anything.
When flatMap calls map, it assigns Option[D] as the value of map's type parameter B (!). So as far as map is concerned, it was passed a function f into some type B, which is actually Option[D] for some type D (but map doesn't care!)
When flatMap calls getOrElse - a similar thing happens, this time getOrElse's type parameter C gets assigned the value Option[B] - and again, getOrElse just "does its thing" without caring that the output happens to be an Option itself
This way, the returned value is:
None if the original input was None (because getOrElse would return the default it was passed)
None if f returned None (because getOrElse would return the value in the Some that it got, which itself is a None)
Some(v) if both the input and the result of f were Some
Which is exactly what flatMap should do.

why can I use map on a function here?

I don't understand why this code compiles :
def lift[A,B](f: A => B): Option[A] => Option[B] = _ map f
If I do :
val f: Int => Double = _.toDouble
Then lift(f) works fine, but f map f gives an error : error: value map is not a member of Int => Double
I don't understand why this code compiles :
def lift[A,B](f: A => B): Option[A] => Option[B] = _ map f
It's short for
def lift[A,B](f: A => B): Option[A] => Option[B] = (o: Option[A]) => o map f
Method lift returns a function that:
- takes an Option[A]
- modifies that option's contents using some function f: A => B
- returns the result, Option[B]
So, when you "lift" some function f: A => B, you basically upgrade it from A => B to Option[A] => Option[B]. When this new upgraded function is given o: Option[A], it will map that option's content into Option[B] (by using f: A => B which was provided when original function was being upgraded).
If I do:
val f: Int => Double = _.toDouble
Then lift(f) works fine, but f map f gives an error error: value map is > not a member of Int => Double
Yes, because you cannot map over a function. You can only map over something by using a function (by the way, things you can map over are called functors).
What you want to do is:
Define some function f (you defined val f: Int => Double = _.toDouble)
Use lift to "upgrade" you function f from Int => Double to Option[Int] => Option[Double]
Use your new upgraded function to map over an Option[Int], thereby transforming it into an Option[Double].
So:
val f: Int => Double = _.toDouble
val upgraded = lift(f)
println(upgraded(Some(8))) // prints Some(8.0)
The lift function simply lifts your function f: A=> B to the function on some other domain, in this case it is Option[_]. So, your implementation of lift gives you a function f': Option[A] => Option[B], and because Option has the map function, you can call it on the first input parameter (this is the 'underscore').
You don't have to call f map f. What you do is lifting your f function:
val f: Int => Double = _.toDouble
val lifted = lift(f)
lifted(Some(42)) //it should be Some(42.0)

How to create lift function

I am trying to create the following lift function but I am hitting a brick wall:
scala> def liftOff[A,B](f : A => B) : A => Option[B] = _.map(f)
<console>:10: error: value map is not a member of type parameter A
def liftOff[A,B](f : A => B) : A => Option[B] = _.map(f)
I thought I could denote that the type parameter A is mappable but the mappable trait is now deprecated since 2.10. If the input type of the returned function is an Option it's not a problem but that is not what I need:
scala> def liftOff[A,B](f : A => B) : Option[A] => Option[B] = _ map f
liftOff: [A, B](f: A => B)Option[A] => Option[B]
Is there a way to do this?
If what you are trying to define is a method that takes a function from A to B, and returns a function from A to Option[B], then you just need to combine f with a function to enclose the result in an Option, such as:
def liftOff[A,B](f : A => B) : A => Option[B] = f andThen Option.apply
if this isn't what you meant, then you might need to edit your question to make your intent clearer.
Another option is to lift* it to the Option type first:
scala> def liftOff[A,B](f : A => B) : A => Option[B] = Some(_) map f
liftOff: [A, B](f: A => B)A => Option[B]
scala> liftOff((x:Int) => 2.0 * x)(3)
res6: Option[Double] = Some(6.0)
*Note: Here Some is the unit/return method lifting A to a monadic (Option) type.

Getting Last Type of Curried Function

Given a val that consists of the following (what I believe is a) type constructor with a curried function argument, F[A => B => C]...
val x: F[A => B => C] = foo() // foo does not matter
Is it possible for me to get F[C] from x?
val y: F[C] = x...
EDIT
For context, I'm trying to implement the map3 function from Functional Programming in Scala.
The only way to get F[C] from F[A => B => C] is if you can apply an A and a B to it. That is, you'll need to evaluate the contained function. Use the apply twice, once to get an B => C and then once again to get C.
def eval(myApp: F[A => B => C])(value: F[A]): F[B => C]
def evalAgain(myApp: F[B => C])(value: F[B]): F[C]
but if you just want to be able to get F[C] directly from the function itself without evaluation, you're SOL.
Edit:
I believe it would look like this.
def eval(myApp: F[A => B => C])(value: F[A], next: F[B])(implicit ap: Applicative[F[_]]) = ap(ap(myApp, value), next)