Currying syntax in scala - scala

The syntax of currying in scala is for example
def f(x: Int, b: Int) = x + y
is
def f(x: Int)(b: Int) = x + y
And currying for sum to sum for given range a and b is
def sum(f: Int => Int, a: Int, b: Int) = {
...
}
sum(x=>x, 3, 6) // outcome is 18 (3+4+5+6)
is
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
}
sum(x=>x)(3, 6) // outcome is 18 (3+4+5+6)
But I don't understand why colon(:)
exists between (f: Int => Int) and (Int, Int)
in def sum(f: Int => Int): (Int, Int) => Int = {
instead of
def sum(f: Int => Int)(Int, Int) => Int = {

Your sum example is not curried. If you wanted it curried you'd do something like:
def sum(f: Int => Int)(a: Int, b: Int): Int =
if (a > b) 0
else f(a) + sum(f)(a + 1, b)
sum(x=>x)(3, 6) // res0: Int = 18
Your code defines a method that takes a single argument, def sum(f: Int => Int). That argument is a function that takes and Int and returns an Int. So no currying involved.
This sum method returns a function, : (Int, Int) => Int. This returned function takes 2 Ints and returns and Int. Invoking this sum method looks like currying, but it's not.
sum(x=>x)(3, 6)
Instead you are invoking sum() with a single argument (x=>x) and then invoking the returned function with two arguments (3,6).

(Int, Int) => Int between : and = specify the function's return type, i.e, it says sum will return another method of signature (Int, Int) => Int which takes two Int and returns another Int, and this is the signature of your inner sumF function:
You can rewrite this to the currying syntax as follows:
def sum(f: Int => Int)(a: Int, b: Int): Int = {
def sumF(a: Int, b: Int): Int =
if (a > b) 0
else f(a) + sumF(a + 1, b)
sumF(a, b)
}
This will more or less do the same thing as the method defined in OP:
sum(x => x)(3, 6)
// res11: Int = 18
But these two definitions are not exactly the same, for instance, for the currying syntax defined here, if you want to generate a new method from it, you have to specify the variable type, like:
val mysum: (Int, Int)=> Int = sum(x => x)
But for the one in OP, it can be simply val mysum = sum(x => x) as the return type of sum as already been specified.

Related

i'm new to scala. can somebody tell me why i'm getting a error illicit start of simple function when writing the def recur function

def fact(n: Int) = products(x => x)(1,n)
fact(5)
def mapReduce(f: Int => Int, combine: (Int, Int) => Int, zero: Int)(a:Int,b:Int): Int =
def recur(a: Int): Int =
if(a>b) zero
else combine(f(a),recur(a+1))
recur(a)
def sum(f: Int => Int) = mapReduce(f, (x, y) => x+y, 0)
def products(f: Int => Int) = mapReduce(f, (x, y) => x*y, 1)
sum(fact)(1,5)
products(fact)(1,5)
def mapReduce(f: Int => Int, combine: (Int, Int) => Int, zero: Int)(a:Int,b:Int): Int = {
def recur(a: Int): Int =
if (a > b) zero
else combine(f(a), recur(a + 1))
recur(a)
}
def sum(f: Int => Int): (Int, Int) => Int = mapReduce(f, (x, y) => x+y, 0)
def products(f: Int => Int): (Int, Int) => Int = mapReduce(f, (x, y) => x*y, 1)
def fact(n: Int) = products(x => x)(1,n)
fact(5)
sum(fact)(1,5)
products(fact)(1,5)
I tried it using scala 2.13 on a scala worksheet, here curly brackets are needed for mapReduce as it contains two expressions one is a function definition and another a function invocation. Secondly when methods that returns functions such as sum and products the return type need to be specified. But I wasn't able to reproduce the error that you mentioned.

Can You Explain this with an example.Encountered this when studying HOF in scala

This is the Function.What are the arguments here?is it a function? and what is the return type?
def sum(f: Int => Int): (Int, Int) => Int = {
def sumf(a: Int, b: Int): Int = {...}
sumf
}
That is a function method called sum. It takes as parameter one function from Int to Int and returns a function that when called with a pair of Ints returns another Int.
The actual result depends on the implementation, but we could for instance define it as:
def sum(f: Int => Int): (Int, Int) => Int = {
def sumf(a: Int, b: Int): Int = {
f(a) + f(b)
}
sumf
}
Or simply:
def sum(f: Int => Int): (Int, Int) => Int = {
(a: Int, b: Int) => f(a) + f(b)
}
In that case, you could call it like this for instance:
def f(a: Int): Int = a * a
def g(a: Int, b: Int): Int = sum(f)(a, b)
val x: Int = g(3, 4) // x = 25

High-Order Function [duplicate]

This question already has answers here:
Currying syntax in scala
(2 answers)
Closed 5 years ago.
In the course of funcional programming with Scala, I saw two form of declaration of a def. But I don't know the diferences between them, and the name given for this. How I can get more information about this?
Declaration 1
def sum(f: Int => Int)(a: Int, b: Int): Int = ???
Declaration 2
def sum(f: Int => Int, a: Int, b: Int): Int = ???
First one is called the curried syntax.
You can apply the function partially, then results in returning of a new function.
scala> def sum(f: Int => Int)(a: Int, b: Int): Int = f(a) + f(b)
sum: (f: Int => Int)(a: Int, b: Int)Int
scala> sum({x: Int => x + 1}) _
res10: (Int, Int) => Int = $$Lambda$1115/108209958#474821de
Second one is uncurried syntax but still we can apply the function partially even in this case.
scala> def sum(f: Int => Int, a: Int, b: Int): Int = f(a) + f(b)
sum: (f: Int => Int, a: Int, b: Int)Int
scala> sum({x: Int => x + 1}, _: Int, _: Int)
res11: (Int, Int) => Int = $$Lambda$1116/1038002783#1a500561
Again new function returned when applied partially.
There is no difference between above two declaration, Its just the syntactic sugar.

why currying does not work with a function literal?

What is the logical reason that the first form works and not the second?
scala> val d = (a: Int, b: Int) => a + b
d: (Int, Int) => Int = <function2>
scala> val d = (a: Int)(b: Int) => a + b
<console>:1: error: not a legal formal parameter.
Note: Tuples cannot be directly destructured in method or function parameters.
Either create a single parameter accepting the Tuple1,
or consider a pattern matching anonymous function: `{ case (param1, param1) => ... }
val d=(a:Int)(b:Int)=>a+b
Because multiple parameter lists aren't allowed on function declarations. If you want to curry a function, you do:
scala> val d: Int => Int => Int = a => b => a + b
d: Int => (Int => Int) = $$Lambda$1106/512934838#6ef4cbe1
scala> val f = d(3)
f: Int => Int = $$Lambda$1109/1933965693#7e2c6702
scala> f(4)
res6: Int = 7
You can also create a single parameter list and partially apply it:
scala> val d = (a: Int, b: Int) => a + b
d: (Int, Int) => Int = $$Lambda$1064/586164630#7c8874ef
scala> d(4, _: Int)
res2: Int => Int = $$Lambda$1079/2135563436#4a1a412e
We partially applied d with 4, and we got back a function, Int => Int, which means when we supply the next argument, we'll get the result:
scala> res2(3)
res3: Int = 7
We can also create a named method, and use eta-expansion to create a curried function out of it:
scala> def add(i: Int)(j: Int): Int = i + j
add: (i: Int)(j: Int)Int
scala> val curriedAdd = add _
curriedAdd: Int => (Int => Int) = $$Lambda$1115/287609100#f849027
scala> val onlyOneArgumentLeft = curriedAdd(1)
onlyOneArgumentLeft: Int => Int = $$Lambda$1116/1700143613#77e9dca8
scala> onlyOneArgumentLeft(2)
res8: Int = 3
Function currying is possible.
val curryFunc = (a: Int) => (b: Int) => a + b
curryFunc now has the type Int => (Int => Int)

Scala function that takes a multiple parameter anonymous function, as a parameter

I have a function named sum that can take a single parameter anonymous function as a parameter, and two Integers.
def sum (f: Int => Int , a: Int, b: Int): Int =
{
if(a > b) 0 else f(a) + sum(f, a + 1, b)
}
sum((x: Int) => x , 2, 10)
How could I modify the function definition so that it can take a multiple parameter function, so I could call it like this:
sum((y: Int, i: Int) => y + i => x , 2, 10)
I know the function I have supplied would be pretty useless when passed a multiple parameter function.. but I am just looking for how it can be done..
Thanks
As simple as this:
def sum (f: (Int, Int) => Int , a: Int, b: Int): Int = ???
Or a curried version:
def sum (f: Int => Int => Int , a: Int, b: Int): Int = ???
Although you can curry any function just calling f.curried