all:
I'm a newbie to scala. I'm not quite understanding an example of curry in the book "functional programming in scala".
Why a function without variables like a, b can be compiled and run smoothly?
def curry[A,B,C](f: (A, B) => C): A => (B => C) =
a => b => f(a, b)
In Scala parameterName => body is an anonymous function that takes a parameter named parameterName and whose body is body.
So a => b => f(a,b) is a function with the parameter a and the body b => f(a,b), which is itself a function with the parameter b and the body f(a,b). In that body a and b are defined because they're parameters.
If that makes it less confusing for you, we can rewrite this using named functions instead:
def curry[A,B,C](f: (A, B) => C): A => (B => C) = {
def f1(a: A) = {
def f2(b: B) = f(a,b)
f2
}
f1
}
It is because
a => b => f(a, b)
is anonymous function (lambda). a and b are variables without any value at the time. They are used only to construct the function (note that curry function return type is another function)
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 have several generic functions with the same signature:
def f1[A, B](v: A, f: (A, B) => B): B = ...
def f2[A, B](v: A, f: (A, B) => B): B = ...
And I need to define a function g that can accept any of these functions (f1 f2):
def g(f: ????) = ...
g internally uses multiple argument types, so I can not parameterize it like that:
def g[A, B](f: (A, (A, B) => B) => B) = ...
There isn't really a much better way to do it in Scala 2. Although your solution is a bit strange because FunctionHolder's apply method will return a function object and doesn't accept any arguments itself – that's a bit more complicated than it needs to be. So you can do this instead:
trait FunctionHolder {
def apply[A, B](v: A, f: (A, B) => B): B
}
def g(f: FunctionHolder) = …
But this isn't really all that much better.
In Scala 3, there are polymorphic function types to do this in a cleaner way:
def g(f: [A, B] => (A, (A, B) => B) => B) = …
That said, I'm not convinced that that type signature is really what you want. Remember, when you define a function with type parameters, it needs to work for all possible type parameters that the user might supply. This can't be done for this signature…
def f1[A, B](v: A, f: (A, B) => B): B
… because when I have a function like that, I can easily write an expression of type Nothing:
f1[Unit, Nothing]((), (a: Unit, b: Nothing) => b)
and it's not possible to write an expression of type Nothing unless you cheat (e. g. throw an exception or enter an infinite loop or something like that). So the type signature tells me you're cheating 😉
If you want to know more about this kind of reasoning, search for “Theorems for free!”
After wandering a bit, come up with following:
g(new FunctionHolder {
def apply[A, B](): (A, (A, B) => B) => B = f1
})
def g(f: FunctionHolder) = f()(..., (a, b) => ...)
abstract class FunctionHolder {
def apply[A, B](): (A, (A, B) => B) => B
}
But that just does not look right.
Hope there are more concise ways to do that
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 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 :-)
I am reading Functional Programming in Scala, and going through different exericses. I encountered currying.
Can someone explain to me this curried function and how does this work? I can seem to understand this piece of code. compared to the ones I saw on different blogs regarding currying in Scala.
def curry[A,B,C](f: (A, B) => C): A => (B => C) = a => b => f(a,b)
is a from a => b => f(a,b) a function if so what are its arguments?
Also update what does this mean? a in a => b => f(a,b) means? is a function that will return a function named b that takes single parameter and will return a function?
I'll assume you understand the concept of currying and that the type definition makes sense to you: A => B => C.
The implementation is: a => b => f(a,b), you could read it as:
... = { a =>
{ b =>
{ f(a,b) }
}
}
So a is the parameter accepted as input of your function of type A => (B => C). And this function returns a second function - of type B => C, that takes b:B and apply f to both.
Edit: you could use this very verbose version if it helps you understand:
def curry[A,B,C](f: (A, B) => C): A => (B => C) = {
def aToBToC(a: A): B => C = {
def bToC(b: B): C = {
f(a,b)
}
bToC
}
aToBToC
}
See how I define private functions in nested scopes? (I haven't tried in the REPL, maybe there is a typo, but you get the idea.)
You defined a function curry which takes an another function as parameter. The return type of that function is A => (B => C), also a function from A to B => C.
After that you defined a implementation of A => (B => C), also for given a return a function b => f(a,b).
Example:
def plus(a: Int, b:Int): Int = a + b
The curried version of plus:
scala> def plusC(a:Int): Int => Int = plus(a, _)
plusC: (a: Int)Int => Int
scala> plusC(1)
res4: Int => Int = <function1>
scala> res4(10)
res5: Int = 11
This is not a curried function. This is a curry method (note: function and methods are very distinct concepts in Scala), i.e. a method that does the currying. Its return value is a curried function; it takes in a function of two arguments and returns a curried function.
def curry[A,B,C] is not curried function itself, it just shows how to convert function that takes two parameters f: (A, B) => C into the curried function A => (B => C). a => b => f(a, b) means that function takes parameter a and returns function b => f(a, b), which in its turn returns final value f(a, b).