I have the following scala code (from the FP In Scala book):
import scala.{Option => _, Either => _, Left => _, Right => _, _} // hide std library `Option` and `Either`, since we are writing our own in this chapter
case class Left[+E](get: E) extends Either[E,Nothing]
case class Right[+A](get: A) extends Either[Nothing,A]
sealed trait Either[+E,+A] {
def map[B](f: A => B): Either[E, B] = this match {
case Right(r) => Right(f(r))
case Left(e) => Left(e)
}
def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] = this match {
case Right(r) => f(r)
case Left(e) => Left(e)
}
def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] = {
this flatMap(aa => b map (bb => f(aa, bb)))
}
}
I would like to know what is going on when I call map2 like this:
val b = fpinscala.errorhandling.Right(2)
val a = fpinscala.errorhandling.Right("right")
val f = (a: String, b:Int) => a + b
a.map2(b)(f)
How does scala know to use substitute this (i.e. a) into the aa in this line of code: this flatMap(aa => b map (bb => f(aa, bb))) in the map2 function?
#jcm, see if this makes any sense.
a.map2(b)(f)
We're calling the map2 method of the a object. Inside the method code a is now referenced as this.
this flatMap(aa => b map (bb => f(aa, bb)))
Now we're calling the flatMap method of the this object (which is still a).
What does flatMap take as an argument? It takes a function, a function that takes an argument (of some type that we'll refer to as "A") and returns an Either. So that means that everything between the parentheses is that function. That function has no name (i.e. no def statement) so it's often called an anonymous function.
That function takes an argument. This code aa => identifies the argument so that it can be referred to later in the function. "aa" is just an arbitrary name. We could have used "thisthat" or "xyz".
Where does the value that aa contains come from? It comes out of this. Consider the following code.
List(4,7,9).map(x => 42 - x)
In this case map invokes the anonymous function three times, once for every value from the List. x takes on a new value (first 4, then 7, then 9) every time the function is invoked.
If that all makes any sense then apply the same logic to b map (bb => .....) and you're almost home!
How does scala know to use substitute this (i.e. a) into the aa
aa is not replaced with this. aa is replaced with the string "right".
The replacement is done by flatMap here:
case Right(r) => f(r)
flatMap checks if this instance of Either is a Right or a Left. If it is a Right, then it feeds its content (the string "right") into the function f (aa => b map (bb => f(aa, bb))).
How does scala know to use substitute this (i.e. a) into the aa in
this line of code: this flatMap(aa => b map (bb => f(aa, bb))) in the
map2 function?
It is not. What is going on here is this:
A closure is being built, which takes an Either[EE,B], calls it aa and computes b map (bb => f(aa, bb). b and f are taken from the parent scope.
this.flatMap is being called, given that function as a parameter.
Read more on Scala closures :-)
Related
I am confused about what this means.
I understand currying but I can't seem to read the code altogether.
def foldLeft [A,B](xs:List[A], e:B, f:(B,A)=>B): B
Let's dive into this method signature:
foldLeft[A,B](xs: List[A], e: B, f: (B, A) => B): B
foldLeft is a method with 3 parameters
A and B are type parameters
xs is 1st parameter of the method, of type List[A]
e is 2nd parameter, of type B
f is 3rd parameter, of type (B, A) => B
the type (B, A) => B represents a function taking two parameters of type B and A respectively, and returning a B
finally, B is the return type of the method
Just a couple of advices.
By the way, there is no currying in
def foldLeft[A,B](xs: List[A], e: B, f: (B, A) => B): B
Currying would be if you had f: B => A => B or def foldLeft[A, B](xs: List[A])(e: B)(f: (B, A) => B): B or def foldLeft[A, B]: List[A] => B => ((B, A) => B) => B etc. Now foldLeft is just a higher-order function (method), i.e. a function accepting another function (f).
You can read wiki article about foldRight/foldLeft:
https://en.wikipedia.org/wiki/Fold_(higher-order_function)
Especially look at the pictures how we deconstruct a list and starting from what end we perform our calculations:
You can think of foldRight/foldLeft as a just short way to define a recursion (instead of pattern matching a list and making recursive calls).
Let's consider an example. Let's have some recursion. For example let's have a wrapper class
case class Value[A](value: A)
And let's transform a list of Value[A] into a value wrapping a list of A i.e. List[Value[A]] into Value[List[A]]. For example we'd like to transform List(Value(1), Value(2), Value(3)) into Value(List(1, 2, 3)) (I actually needed such function recently). Surely, we could do this with .map but let's pretend that we don't know map (it shouldn't be surprising that we can do mapping because map can be expressed via foldRight/foldLeft).
We can do this recursively in two ways (at least). Either simple recursion
def valuesToValue[A](values: List[Value[A]]): Value[List[A]] = values match {
case Nil => Value(Nil)
case v :: vs => Value(v.value :: valuesToValue(vs).value)
}
or tail recursion with a helper function and accumulator
def valuesToValue[A](values: List[Value[A]]): Value[List[A]] = {
#tailrec
def loop(values: List[Value[A]], acc: Value[List[A]]): Value[List[A]] = values match {
case Nil => Value(acc.value.reverse)
case v :: vs => loop(vs, Value(v.value :: acc.value))
}
loop(values, Value(Nil))
}
Very simple. Just wrapping-unwrapping.
Both recursive implementations of valuesToValue can be (automatically) re-written with foldRight/foldLeft.
The former recursion can be re-written with foldRight. The latter recursion (tail one) can be re-written with foldLeft.
Let's re-write the 1st recursion with foldRight. The value from branch case Nil => ... becomes the 1st argument of foldRight. The value from branch case v :: vs => ... becomes the 2nd argument of foldRight if we replace the result of recursive call valuesToValue(vs) with a new variable res, so in the 2nd argument of foldRight we'll have a function of v: Value[A] and res: Value[List[A]]
def valuesToValue[A](values: List[Value[A]]): Value[List[A]] =
values.foldRight( Value(Nil: List[A]) ){
(v, res) => Value(v.value :: res.value)
}
Let's re-write the 2nd recursion (tail one) with foldLeft.
First of all, let's recall that because of currying we can understand the helper loop as a single-parameter function into Value[List[A]] => Value[List[A]]
def loop(values: List[Value[A]]): Value[List[A]] => Value[List[A]] = values match {
case Nil => acc => Value(acc.value.reverse)
case v :: vs => acc => loop(vs)(Value(v.value :: acc.value))
}
Now the value from branch case Nil => ... becomes the 1st argument of foldLeft. The value from branch case v :: vs => ... becomes the 2nd argument of foldLeft if we replace the result of recursive call loop(vs)(_) with a new variable res (a function)
def valuesToValue[A](values: List[Value[A]]): Value[List[A]] = {
def loop(values: List[Value[A]]): Value[List[A]] => Value[List[A]] =
values.foldRight[Value[List[A]] => Value[List[A]]](
acc => Value(acc.value.reverse)
)(
(v, res) => acc => res(Value(v.value :: acc.value))
)
loop(values)(Value(Nil))
}
So, roughly speaking, values from branches case Nil => ... and case v :: vs => ... become arguments of foldRight/foldLeft depending on whether we calculate with simple recursion or tail recursion with accumulator.
I am having problems understanding this code from the Book FP in Scala. Here is the code:
trait Monoid[A] {
def op(a1: A, a2: A): A
def zero: A
}
def endoMonoid[A]: Monoid[A => A] = new Monoid[A => A] {
def op(f: A => A, g: A => A) = f compose g
val zero = (a: A) => a
}
def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B =
as.foldLeft(m.zero)((b, a) => m.op(b, f(a)))
// The function type `(A, B) => B`, when curried, is `A => (B => B)`.
// And of course, `B => B` is a monoid for any `B` (via function composition).
def foldRight[A, B](as: List[A])(z: B)(f: (A, B) => B): B =
foldMap(as, endoMonoid[B])(f.curried)(z)
foldMap is expecting a function f: A => B.
In foldRight, when f is curried you have A => (B => B), so I suppose f.curried is working because it is the same as (A => B => B), so foldRight is passing in to foldMap what it expect (a function with type A => B), then, what happends next is that foldMap is called and its returning a function B => B, and that's when z comes into play in (f.curried)(z) you call the function B => B with the argument z to get the final B.
Am I right? it is a litle complicated to reason about this code for me.
NOTE: Here is a scalafiddle if you want to play with it.
Well, you seem to be mostly comprehensive to me. Nevertheless, I would clarify some points:
I'd rather say "so I suppose f.curried is working because A => (B => B) is the same as (A => B => B)" (it is ambiguous here and you're talking about f.curried result type basically, not with z)
I'd rather put a point instead of a comma here: "foldMap is expecting a function f: A => B . In foldRight, ... " and pretty much every where else. Shorter phrases, clearer explanation.
what could be an error, (and what is confusing to you?) is that (f.curried)(z) doesn't work on its own and is not called after foldMap(as, endoMonoid[B]). It's first foldMap(as, endoMonoid[B])(f.curried) which is called and then (z). The first returns B => B and called with the second returns B.
I'm having trouble deciphering the following function. Particularly, the flatMap line - where are the 'aa' and 'bb; variables coming from, and how is this executed? Maybe if someone could explain in words what is happening with this code it would be helpful. I'm just really struggling how to read this syntax.
def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] =
this flatMap(aa => b map (bb => f(aa, bb)))
Here is the flatMap function:
def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] = this match {
case Right(r) => f(r)
case Left(e) => Left(e)
}
and map:
def map[B](f: A => B): Either[E, B] = this match {
case Right(r) => Right(f(r))
case Left(e) => Left(e)
}
Looks like all these functions are defined for Either class. Either can be in two 'states' - Right - correct value and Left which interpreted ass error.
Lets go from the map definition. We have Either parametrized with type A. map accepts function converting type A to B. So map function checks if value is Right then it applies given function f to Right value, wraps it with Right and return. If error then just return error.
Right[String, Int](4).map(_*3) // gives Right(12)
Left[String, Int]("error").map(_*3) // gives Left("error")
flatMap is similar to map, but accepts function converting type A to Either of right type B, so unlike map we don't need to wrap right value
Right[String, Int](5).flatMap(item => Right(item*3)) //gives Right(15)
Left[String, Int]("error").flatMap(item => Right(item*3)) //gives Left("error")
As defined, map2 takes instance of Either b and function, converting pair of values of types A and B to some third value C, and return the result wrapped with Either. Let's take closer look at how it is implemented.
this.flatMap(aa => b map (bb => f(aa, bb)))
lets rewrite it with definition of flatMap:
this.match {
case Right(r) => b.map (bb => f(r, bb))
case Left(e) => Left(e)
}
And apply map:
this.match {
case Right(r) => {
b match {
case Right(br) => Right(f(r, br))
case Left(be) => Left(be)
}
}
case Left(e) => Left(e)
}
So there are three paths:
if right a and right b then apply function(a,b)
if right a and error b then error(b)
if error a then error a
Examples:
Right(7).map2(Right(4)){case (a,b) => a*b} // gives Right(28)
Right(7).map2(Left[String, Int]("failed")){case (a,b) => a*b} //gives Left("failed")
Left[String, Int]("error").map2(Left[String, Int]("failed")){case (a,b) => a*b} //gives Left("error")
Edit: Inner function explanation
You have to pass to a flatMap function with type:
A => Either[EE, C]
It means "take an argument of type A and convert it to result of type Either[EE,C]"
so you could define:
def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] = {
def func(aa:A):Either[EE, C] = {
b map (bb => f(aa, bb))
}
this flatMap(func)
}
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)
If I have a function:
f : A => B => C
I can define an implicit conversion such that this can be used where a function (A, B) => C is expected. This goes in the other direction also.
Why are these conversions not implicit (or available implicitly)? I am assuming that bad things could happen for some value of bad things. What value is this?
I don't think anything bad will happen. The conversion is completely unambiguous. Worst case, Scala will not be able to figure out that the implicit conversion applies.
implicit def curryImplicitly[A,B,C](f: (A, B) => C) =
(a: A) => (b: B) => f(a, b)
implicit def uncurryImplicitly[A,B,C](f: A => B => C) =
(a: A, b: B) => f(a)(b)
Then again, these would also be helpful.
implicit def flipImplicitly[A,B,C](f: (A, B) => C) =
(b: B, a: A) => f(a, b)
implicit def flipImplicitlyCurried[A,B,C](f: A => B => C) =
(b: B) => (a: A) => f(a)(b)
But those aren't transitive, so you need these:
implicit def flipAndCurry[A,B,C](f: (A, B) => C) =
(b: B) => (a: A) => f(a, b)
implicit def flipAndUncurry[A,B,C](f: A => B => C) =
(b: B, a: A) => f(a)(b)
But now the conversion is ambiguous. So it's not all roses.
Let's know how it works out in practise. You might need equivalents for Function3, Function4, etc.
You don't want them implicitly available by default (always-on) because then the type system has trouble helping you out when you have overloaded with arguments of a bunch of similar types:
A => B => C
D => C // D is allowed to be a tuple (A,B)...
(A,B) => C // If I have this, to whom should I convert?
Part of the advantage of strong typing is warning you when you've done something foolish. Trying too hard to make things work reduces the benefits. Here, if the conversions were done automatically, you might not call the method you meant to call.
Having them available implicitly upon request is fine, but it's not that hard to do it yourself if you need it. This is something that I would use quite rarely; I wouldn't put it in my top ten or probably even top hundred things that I'd like in the library (in part because I might prefer the automatic conversion to a tuple instead of the automatic currying/uncurrying).