joachim
joachim

Reputation: 692

Scala Curried Type Mismatch

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?

Upvotes: 4

Views: 162

Answers (3)

Terry Dactyl
Terry Dactyl

Reputation: 1868

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..

Upvotes: 0

sarveshseri
sarveshseri

Reputation: 13985

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.

Upvotes: 6

Rhys Bradbury
Rhys Bradbury

Reputation: 1707

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.

Upvotes: 0

Related Questions