Scala Curried Type Mismatch - scala

So i got the following function after some trial and error and research in our Textbook i could come up with a solution.
def prodC1(f : Int => Int) : (Int, Int) => Int = {
def prodA1(a : Int, b : Int) : Int =
if(a > b) 1 else f(a) * prodA1(a+1, b)
prodA1 // Why do i need this line here
}
If I don't put that there i get a Type mismatch, could someone elaborate/explain the requirement for this Line?

So there are a lot of things which you need to know to actually understand the answer to this.
In Scala any def is a method which is nothing more than one of the members of some object. methods are not first class members in Scala which also means that methods can not exist on their own.
In Scala, the value of anything needs to be an expression. Meaning the RHS for a def needs to be an expression like def abc = some-expression. Examples of expression are 1, 1 + 1, "xyz", anotherMethodCallWhichWillReturnAnExpression() etc.
And something like def abc = xxxxxx is not an expression in Scala language definition. And hence you can not do,
def prodC1(f : Int => Int) : (Int, Int) => Int = {
def prodA1(a : Int, b : Int) : Int =
if(a > b) 1 else f(a) * prodA1(a+1, b)
}
Now, when you are adding that extra line with prodA1, you are telling Scala to return this prodA1 which you just define. But remember prodA1 is just a method and hence can not exist on its own and hence can not actually be returned.
But functions are first class members in Scala (represented as instances of one of the various FunctionX classes) and hence can be returned.
In this case Scala will intelligently lift this method to become a function of type (Int, Int) => Int. This is called eta-expansion.
To understand things more in detail. You can open the Scala console and try the following.
scala> val s = "abc"
// s: String = abc
scala> val i = 10
// i: Int = 10
scala> def prodA1(a : Int, b : Int) : Int = if (a > b) 1 else a * prodA1(a+1, b)
// prodA1: (a: Int, b: Int)Int
Notice the difference between the output of Scala console for actual values and def. Now, if I try to use prodA1 as value of a val, I will get following error.
scala> val x = prodA1
// <console>:12: error: missing argument list for method prodA1
// Unapplied methods are only converted to functions when a function type is expected.
// You can make this conversion explicit by writing `prodA1 _` or `prodA1(_,_)` instead of `prodA1`.
// val x = prodA1
Scala is telling you that you can explicitly convert method to function by using a _. Lets try that.
scala> val x = prodA1 _
// x: (Int, Int) => Int = $$Lambda$1077/293669143#13278a41
Now x is a function of type (Int, Int) => Int.
Also, that first line Unapplied methods are only converted to functions when a function type is expected. is telling you about what actually happened in your case.
Since prodC1 was expected to return a function of type (Int, Int) => Int and you provided prodA1, Scala used eta-expansion to automatically convert your method to function.

Let's have a look at your return type.
def prodC1(f : Int => Int) : (Int, Int) => Int = {
def prodA1(a : Int, b : Int) : Int =
if(a > b) 1 else f(a) * prodA1(a+1, b)
prodA1 // Why do i need this line here
}
your return type is
(Int, Int) => Int
that is scala sugar for a Function2[Int, Int, Int]
where the first param is the type to the first param, the second param is the type for the second param and the last is the type for the return param
The return instance needs to be a function
prodA1 conforms to this type, meaning it is allowed to be returned.

Your function needs to return an instance of (Int, Int) => Int.
def prodA1(a : Int, b : Int) : Int =
if(a > b) 1 else f(a) * prodA1(a+1, b)
Creates a function of type (Int, Int) => Int with name prodA1 but the return type of defining an inner function does not create an instance of anything so the return type of the function is Unit.
Therefore you need to return the prodA1 which has the correct type..

Related

Invoking higher order functions - Scala

Hi I am new to Scala and trying to call a higher order function sum_of from main class.I am getting "Cannot resolve reference sumOf with such signature error".
object SumOf {
def main(args: Array[String]) {
val y = sumOf(x=>x ,4,5)
println(y)
}
def sumOf(f: Int => Int)(a: Int, b: Int): Int = {
def loop(a: Int, acc: Int): Int =
if (a > b) acc
else loop(a + 1, f(a) + acc)
loop(a, 0)
}
}
sumOf is a curried function so it takes two arguments in the form of sumOf(x => x)(4,5) which is different from sumOf(x => x, 4,5). This is the reason you are getting an error.
Further, you can call it with only one argument sumOf(x => x) _ which returns another function that takes the second argument
(Int, Int) => Int = <function2> and return a function. This is more commonly known as partial function application.
Your sumOf method has two argument lists, and needs to be called with two argument lists.
val y = sumOf(x => x)(4, 5)
You can think of sumOf as a function which takes an Int => Int and returns a new function, which takes two Ints to return an Int.

Partially applied function in scala

I am trying to understand Partially applied function in scala
scala> val a=sum _
a: (Int, Int, Int) => Int = <function3>
scala> a(1,2,3)
res7: Int = 6
I am just giving this val a=sum _
I want to understand how scala interprets it will take 3 arguments
a: (Int, Int, Int) => Int = <function3>
You've just experienced the eta-expansion that is converting a method into a function.
Your method is sum which you are not demonstrating but based on the function version must be:
def sum(a:Int,b:Int,c:Int):Int = a + b + c
The underscore you are adding at the end is converting your method into a function as the descriptive type signature of the result shows: (Int, Int, Int) => Int
This way you are converting your method into a function value that can be assigned to a variable and passed around in your application logic conveying a behavioural change to your data (addition in your instance).

Why need I denote the type for partial applied function on the known type parameter?

Given the
def sum(a: Int, b: Int) = a + b
val add7 = sum(7, _)
// compiler complains missing $x1's type for $x1 => sum(7, $x1)
val add8 = sum(8, _: Int)
// fine
And curried sum can do this without type declaration .
def sum_curry(a: Int)(b: Int) = a + b
val add9 = sum_curry(9)(_)
// fine
But it's not a generic function, what sum's parameter types can be known and it is already there.
Why cannot Scala know the $x1's type from b: Int in sum's signature?
The compiler needs to know the data types of function arguments to map a function call to exactly one function definition (out of many overloaded function definition of with same name)
It will become ambiguous if we try a reverse mapping from function definition to function call to determine the type of a parameter in function call.
Eta expression can convert this to a value type (Int, Int) => Int only when:
_ as in place of the argument of list
val f = sum _
or, you just omit the argument list.
val f :(Int, Int) => Int = sum
and specify its type.
or use each _
val f = sum(_ , _)
As you can see, sum(7, _) cannot satisfy any of above.

Scala function definitions and usage

Based on below examples of defining functions what is the best use of 2 and 3 in different scenarios?
def sum(x: Int, y: Int): Int = { x+y }
This is a function definition with arguments, return type and function body
val sum = (x: Int, y: Int) => { x+y }
This seems like an assignment of lambda function to a variable, why return type is never defined here?
val sum: (Int, Int) => Int = (x,y) => { x+y }
This is defining a function as a type?
I don't understand how this works!
All 3 functions when invoked will yield the same result:
scala> sum(1,2)
Int = 3
def sum(x: Int, y: Int): Int = { x+y }
This is a function definition with arguments, return type and function body
This is not a function definition. This is a method definition. Functions and methods are fundamentally different. Functions are objects, methods are not. (Methods belong to objects.) Methods can be polymorphic, functions can't.
val sum = (x: Int, y: Int) => { x+y }
This seems like an assignment of lambda function to a variable, why return type is never defined here?
Are you asking why the type of sum isn't declared or why the return type of the function literal isn't declared? The return type of the function literal isn't declared because there is no way in the syntax to do so. You simply cannot declare the return type of a function literal, it is always inferred. The type of sum isn't declared because it is not necessary: it can be inferred to be the same as the type of the function literal, i.e. Function2[Int, Int, Int].
Think val foo = "Hello".
val sum: (Int, Int) => Int = (x,y) => { x+y }
This is defining a function as a type?
No. This is the exact same thing as 2., except that here the type of sum is explicitly declared (as (Int, Int) => Int which is syntactic sugar for Function[Int, Int, Int]) instead of inferred. Since the type of sum is known, you can leave off the types of the function parameters, because they can be inferred from the context.
Think val foo: String = "Hello".
In line 2, scala compiler inferences type of lambda function.
val sum = (x: Int, y: Int) => { x + y }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function value
x and y are type of Int, thus x + y is a Int type. In this case, type of sum is (Int, Int) => Int.
In line 3, it shows the type of sum - (Int, Int) => Int. sum indicates a function same with line 2.
val sum: (Int, Int) => Int = (x,y) => { x+y }
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
type function value
Right side of = is function signature and body. It receives two arguments called x and y. Its body is x + y.
Shortly, line 2 and line 3 are equivalent. Line 2 has no type of function value, but scala can inference its type. Line 3 has type of function value explicitly, and omits argument type of signature of function value.
this is about the difference between method and function. The useful link to show the difference is http://java.dzone.com/articles/revealing-scala-magician%E2%80%99s
I think in the 3rd way, you can understand it like a type T = (Int, Int) => Int and then do this : val sum: T = (x,y) => { x+y }
another thing is that if remove input arguments, method and function is different.
def sum: Int = { 3 } //call sum, get 3
val sum: () => Int = () => { 3 } //call sum, return a function, need to call sum() to get 3

What's the advantage of using multiple lists of function parameters?

scala> def a(i:Int)(j:Int) = i * j
a: (i: Int)(j: Int)Int
scala> def b(i:Int, j:Int) = i * j
b: (i: Int, j: Int)Int
The two definitions are very similar, and they (appear to me) do the same thing.
Apart from defining a function which receives implicit parameters or a code block as parameter, is there any reason to use the first definition style?
This is the list I have compiled over the time:
1) Type resolution across multiple argument lists
class ResourceManager {
type Resource
def open: Resource = ???
}
class ResourceManagerTest {
// Does not compile: def test1(rm: ResourceManager, r: rm.Resource) = ???
// Compiles: This way the type can be resolved
def test2(rm: ResourceManager)(r: rm.Resource) = ???
}
2) Type inference where earlier arguments can "lock down" type parameters for later arguments (thanks to Myserious Dan)
def foo1[A](x: A, f: A => Int) = ???
def foo2[A](x: A)(f: A => Int) = ???
def foo1foo2Demo() {
// This will always demand a type annotation on any anonymous function
// you pass in:
foo1(1, (i: Int) => i * i)
// Does not compile: foo1(1, i => i * i)
// Type not required
foo2(2)(i => i * i)
}
3) Syntax-like language extensions
object MultipleArgumentListsDemo {
// This style of function definition allows syntax-like language extensions
#tailrec
def myWhile(conditional: => Boolean)(f: => Unit) {
if (conditional) {
f
myWhile(conditional)(f)
}
}
def myWhileDemo() {
var count = 0
myWhile(count < 5) {
count += 1
println(count)
}
}
4) Having both implicit and non implicit arguments, as implicit is a modifier for a whole argument list:
def f[A](x: A)(implicit mf: Manifest[A]) {
}
5) A parameter's value from one parameter list can be used to compute a default value in another parameter list, but not in the same one.
def g(x: Int)(y: Int = x * 2) = {
x + y
}
6) Multiple repeated argument lists ("varargs")
def h(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum
7) Partial application
def i() {
val foop = h(1, 2, 3)(4, 5, 6, 7, 9) _
println(foop(Seq(10, 11)))
}
As I have not tracked my sources while I was compiling that list over the time: It's possible that some or all examples are copied from elsewhere (other questions on SO), so please drop a note, and I will add the reference as to where it came from.
The main reason for "currying" functions in this manner is to enable partial application:
scala> val c = a(5) _
c: Int => Int = <function1>
Here c is a function that takes a single int and returns the result of multiplying that int with 5. It may be that you would set up c in one method, and pass it into another method that expects a function taking one Int parameter. A bit trivial in this case, but very flexible for a range of uses.
Additional to support currying, it also helps with type inference: Sometimes the compiler can't infer the correct type if everything is in one argument list, but if you split off the part that depends on the binding of the other arguments, it works. A typical example is foldLeft: Try to implement it with one argument list, and then in some cases the compiler needs type annotations.