I am very very new to Scala. I am reading a book called functional programming in scala by Paul Chiusano and Rúnar Bjarnason. So far I am finding it interesting. I see a solution for curry and uncurry
def curry[A,B,C](f: (A, B) => C): A => (B => C)= {
a => b => f(a,b)
}
def uncurry[A,B,C](f: A => B => C): (A, B) => C = {
(a,b) => f(a)(b)
}
In Curry I understand f(a,b) which results in value of type C but in uncurry I do not understand f(a)(b). Can anyone please tell me how to read f(a)(b) or how is this resulting to a type of C or please refer me some online material that can explain this to me?
Thanks for your help.
Basically the return type of f(a) is a function of type B => C lets call this result g.
If you then call g(b) you obtain a value of type C.
f(a)(b) can be expanded to f.apply(a).apply(b)
In the uncurry method you take a so-called "curried" function, meaning that instead of having a function that evaluates n arguments, you have n functions evaluating one argument, each returning a new function until you evaluate the final one.
Currying without a specific support from the language mean you have to do something like this:
// curriedSum is a function that takes an integer,
// which returns a function that takes an integer
// and returns the sum of the two
def curriedSum(a: Int): Int => Int =
b => a + b
Scala however provides further support for currying, allowing you to write this:
def curriedSum(a: Int)(b: Int): Int = a + b
In both cases, you can partially apply curriedSum, getting a function that takes an integer and sums it to the number you passed in originally, like this:
val sumTwo: Int => Int = curriedSum(2)
val four = sumTwo(2) // four equals 4
Let's go back to your case: as we mentioned, uncurry takes a curried function and turns it into a regular function, meaning that
f(a)(b)
can read as: "apply parameter a to the function f, then take the resulting function and apply the parameter b to it".
In case if somebody is looking for an explanation. This link explains it better
def add(x:Int, y:Int) = x + y
add(1, 2) // 3
add(7, 3) // 10
After currying
def add(x:Int) = (y:Int) => x + y
add(1)(2) // 3
add(7)(3) // 10
In the first sample, the add method takes two parameters and returns the result of adding the two. The second sample redefines the add method so that it takes only a single Int as a parameter and returns a functional (closure) as a result. Our driver code then calls this functional, passing the second “parameter”. This functional computes the value and returns the final result.
Related
This question already has answers here:
Understanding Currying in Scala
(3 answers)
Closed 4 years ago.
def sum(f: Int => Int): (Int, Int) => Int = {
def sumF(a: Int, b: Int): Int =
if (a > b) 0
else f(a) + sumF(a + 1, b)
sumF
}
def sumCubes = sum(a => a * a * a)
sumCubes // output Function2
sumCubes(1,10) // output 3025.
sumCubes() // doesn't work
I feel I dont understand currying well enough. In the first statement , we are calling sumCubes without parameters , hence sum gets called with the anonymous function as parameter and returns a function2.
Whats really happening in 2nd and 3rd invocation ,
Why are we able to do
sum(a => a * a * a)(1,10)
but not
sumCubes()(1,10)
My understanding is that in sum(a => a * a * a)(1,10) , we are partially applying sum to the anonymous function, which returns a Function2 ,which is applied to the second pair of parameters (1,10) and hence we are getting 3025,
However the same should happen in case of sumCubes()(1,10) , invoking sumCubes without parameters first , would inturn invoke sum with the anonymous function and the Function2 returned would be applied to (1,10)
Why does sumCubes(1,10) work but not sumCubes()(1,10) , shouldn't sumCubes and sumCubes() mean the same thing , invocation of function sumCubes. Also if a simple reference sumCubes is invoking it , how can I pass it around. I feel like I am not understanding something fundamental about Scala.
Scala's methods can have multiple argument lists.
For example, here is a method foo that has ten argument lists, of which the first seven are empty:
def foo()()()()()()()(a: Int)(b: Int)(c: Int): Int = a + b + c
You can invoke it as follows:
println(foo()()()()()()()(1)(20)(300))
and it will print 321.
Note that when you invoke a method, the number of argument lists, as well as the number of arguments in each list (and also their types) have to match the declaration.
Another example. The following method has two argument lists:
def bar(i: Int)(f: Int => Int) = f(i)
you can invoke it as follows:
bar(42)(x => x * x)
but not as
bar()(x => x * x)
bar()(42)(x => x * x)
bar(42)()
or anything like it.
Completely analogously, if you have defined a method with zero argument lists
def baz = (x: Int) => x * x
then you must invoke it with zero argument lists too:
baz
Since it returns an Int => Int function, you can of course apply the result to an Int:
baz(42)
which is the same as (baz)(42), but you cannot do the following:
baz()(42)
because baz itself has no argument lists, and () does not contain a single integer argument.
Note that all of the above is actually a simplification: under certain circumstances, methods that have an empty argument list can be called without parentheses, i.e. def foo(): Unit = ... can be invoked as foo, without (). This is a somewhat strange feature, and I can't say exactly why it's there. My best guess would be: it has something to do with java-interop, where you really want to omit parentheses on zero-ary getters.
I understand how does a curried function work in practice.
def plainSum(a: Int)(b: Int) = a + b
val plusOne = plainSum(1) _
where plusOne is a curried function of type (Int) => Int, which can be applied to an Int:
plusOne(10)
res0: Int = 11
Independently, when reading the book (Chapter 2) Functional Programming in Scala, by Chiusano and Bjarnason, it demonstrated that the implementation of currying a function f of two arguments into a function of one argument can be written in the following way:
def curry[A, B, C](f: (A, B) => C): A => (B => C) =
a: A => b: B => f(a, b)
Reference: https://github.com/fpinscala/fpinscala/blob/master/answers/src/main/scala/fpinscala/gettingstarted/GettingStarted.scala#L157-L158
I can understand the above implementation, but have a hard time associating the signature with the plainSum and plusOne example.
The 1 in the plainSum(1) _ seems to correspond to the type parameter A, and the function value plusOne seems to correspond to the function signature B => C.
How does the Scala compiler apply the above curry signature when seeing the statement plainSum(1) _?
You are conflating partially applying a function with currying. In Scala, they some differences:
A partially applied function passes less arguments than provided in the application with the rest of the arguments, represented by the placeholder(_), is partially applied on the next call.
Currying is when a higher order function takes a function of N arguments and transforms it into a one-arg chains of functions.
The plusOne example is naturally curried out of the box by virtue of the multi-parameter list which takes a function of one argument successively and return the last argument.
Your mistake is that you are trying to use currying twice when this notation()() already gives you currying.
Meanwhile you can achieve same effect by currying the plainSum signature to the curry function like so:
def curry[A, B, C](f: (A, B) => C): A => (B => C) =
(a: A) => (b: B) => f(a, b)
def plainSum(a: Int, b: Int) = a + b
val curriedSum = curry(plainSum)
val add2 = curriedSum(2)
add2(3)
Both(partial application and currying) shouldn't be confused with another concept called partial functions.
Note: The red book, fpinscala, tried creating those abstraction as done in the Scala library without the syntactic sugar.
I'm having hard times trying to create a Scala Test to checks this function:
def curry[A,B,C](f: (A,B) => C): A => (B => C) =
a => b => f(a,b)
The first thought I had was to validate if given a function fx passed into curry(fx) function, will return a curried version of it.
Any tips?
One way to test it, is to pass different f's to it and see if you are getting back the function you expect. For example, you can test an f that returns the arguments as a tuple:
def f(x: String, y: Int) = (x, y)
curry(f)("4")(7) must be(("4", 7))
IMO, testing it for a few different functions f and for a few different a and b would be more than sufficiently assuring that something as trivial as this works as intended.
scala> def lift3[A,B,C,D] (
| f: Function3[A,B,C,D]): Function3[Option[A], Option[B], Option[C], Option
[D]] = {
| (oa: Option[A], ob:Option[B], oc: Option[C]) =>
| for(a <- oa; b <- ob; c <- oc) yield f(a,b,c)
| }
lift3: [A, B, C, D](f: (A, B, C) => D)(Option[A], Option[B], Option[C]) => Option[D]
In particular, the following line:
def lift3[A,B,C,D] (
f: Function3[A,B,C,D]): Function3[Option[A], Option[B], Option[C], Option
[D]]
This is taken from the book Scala In Depth by Joshua D Suereth (Listing 2.1, chapter 2). I'm not sure what purpose the additional Option[D] serves. In the body of the function, the code only maps to the first three parameters to the output type D. When then, D is declared in the input parameter list? Am I missing something?
With my limited understanding, I would read the function declaration as a function that takes a function as a parameter (which in turn takes 4 parameters) and returns a function that takes 4 parameters. Also, why is there no mention of the return type?
Thanks in advance!
With my limited understanding, I would read the function declaration as a function that takes a function as a parameter (which in turn takes 4 parameters) and returns a function that takes 4 parameters. Also, why is there no mention of the return type?
Function3[A,B,C,D] is a function with 3 parameters (of types A, B and C) and D is the return type (it can also be written as (A, B, C) => D; this is exactly the same type). So in Function3[Option[A], Option[B], Option[C], Option[D]], Option[D] is the return type, not a parameter type.
A function3 takes 3 parameters. The D is the return type of the function. What the code does, is take a function with 3 arguments and return a function with 3 arguments, where each argument and its return type is "lifted" to an Option.
You can check out the API docs for Function3 here.
And an explanation for the R generic type can be found in the docs for Function2
w.r.t Currying in scala, partly I understood below sample code.
def product1(f:Int => Int )(a:Int, b:Int):Int = {
println()
if(a > b ) 1
else
f(a) * product1(f)(a+1, b)
}
product(x => x * x) (3, 4)
Out of it., I am bit confused with
product1(f)
in
product1(f)(a+1, b)
Just need explanation, what goes on here.... :( and how to pronounce verbally while explaining...
Thanks in advance..
product1 has two parameter lists. product1(f) is the application of f which is a function of kind Int => Int. If you were only to call product1(f) like so:
product1(f)
without the second parameter list, you'd get a so-called partially-applied function, i.e. a function which doesn't have all of its parameters bound (you'd still need to provide it with a and b)
Look at the parameter declaration:
f:Int => Int
f is a function that maps an Int to an Int -- it takes an Int as an argument and returns an Int. An example is given:
x => x * x
returns the square of its argument.
product1(x => x * x) (3, 4)
returns the product of f(3) .. f(4) = 3*3 * 4*4
BTW, this isn't really an example of currying, since all the arguments are given. Currying would be something like
val prodSquare = product1(x => x * x)
Then,
prodSquare(1, 5)
yields 1*1 * 2*2 * 3*3 * 4*4 * 5*5
For most idiomatic purposes I've seen, you may as well think of your function as having just one parameter list. Multiple parameter lists are used mostly for type inference purposes in generic functions, since type inference is done one parameter list at a time, rather than using Hindley-Milner/Algorithm W to infer the type of everything at once. Some other language features work on individual parameter lists, such as implicit parameters and implicit use of braces in place of parentheses for single-parameter parameter lists, etc.
Functions with multiple parameter lists are called in a similar way to a curried functions from a syntactic perspective, but by default, the intermediate functions aren't created. In fully curried style, each function takes only at most one argument and returns one result (which might happen to be another function, which expects on argument, and so forth). Technically, currying the function would be:
def product2(f: Int => Int): Int => Int => Int = {
a: Int => {
b: Int => {
if(a > b ) 1
else f(a) * product2(f)(a+1)(b)
}
}
}
For completeness, you can treat a function with multiple parameter lists as a curried function by using an underscore after a complete parameter list. In your original example, you'd do product1(f)_, which would return a function of type (Int, Int) => Int.
In researching this question, I came upon another SO question worth checking out to understand this aspect of the language better.