How are functions in curry (with one argument) different from methods?

I am having a hard time understanding how cardinal functions (with one argument) differ from regular methods. I tried to implement the latter with the former, but failed.

I have a trait Market

defined like this:

package market {
  trait Market {
    def getBuyRate(currency: String): Double
    def getSellRate(currency: String): Double
  }
}

      

I have another trait FakeMarket

that expands Market

where I wanted to use currying to implement getBuyRate

and getSellRate

as follows:

package market { 
  trait FakeMarket extends Market with Iterable[Double] {
    def getRate(factor: Double)(currency: String): Double = {
      factor * this.iterator.next()
    }
    def getBuyRate = getRate(1) _
    def getSellRate = getRate(1.02) _
  } 
}

      

Finally, I have an object RandomFakeMarket

that extends FakeMarket

:

package market {
  object RandomFakeMarket extends FakeMarket {
    def iterator = new Iterator[Double] {
      def hasNext = true
      def next = 100.0
    }
  }
}

      

Having types defined as such gives an error:

<console>:10: error: object creation impossible, since:
it has 2 unimplemented members.
/** As seen from object RandomFakeMarket, the missing signatures are as follows.
 *  For convenience, these are usable as stub implementations.
 */
  def getBuyRate(currency: String): Double = ???
  def getSellRate(currency: String): Double = ???

       object RandomFakeMarket extends FakeMarket {
              ^

      

It seems strange to me because it FakeMarket

implements methods with name getBuyRate

and getSellRate

type String => Double

.

I can get this to work if in Market

I did:

getBuyRate: String => Double

      

Why is this different from how I originally defined it getBuyRate

? Why should it be different when there is only one argument? Now it seems like the parent trait Market

should be concerned about how it is implemented getBuyRate

(normal function versus curried function).

+3


source to share


1 answer


It has less to do with curry. def method(p1: String, p2: String): String

not equivalent def method: (String, String) => String

in scala. The difference between methods and functions is that methods support inheritance, so they need to know the input and output method , which is not so obvious due to the ambiguity:

def get: String => Double

can be either String -> Double

(iterpreted as a unified member) or () -> String -> Double

(interpreted as a function). But in scala it is Function1[String, Double]

or () Function1[String, Double]

, which looks like there is no input. Unfortunately, def get(): String => Double

it doesn't matter here (see examples below).

In other words, a method may not have an input parameter in scala (as it may not be a pure function due to side effects), so it cannot infer (String)Double

from String => Double

, so your whole function will become an output parameter. For example, you can do override def method: (String, String) => String

in any subclass - this will override the method with no parameters and with a return type (String, String) => String

, but it does not override the method with input (String, String)

and return the type String

.



Another problem is that methods are of different types than functions, and can only be unidirectional, converted with the eta extension, so scala is a bit incompatible with UAP :

scala> def aaa(b: String): String = "aaa"
aaa: (b: String)String

scala> aaa _
res4: String => String = <function1>

scala> def aaa: String => String = (a: String) => "aa"
aaa: String => String

scala> def aaa()(b: String): String = "aaa"
aaa: ()(b: String)String

scala> def aaa(): String => String = (a: String) => "aa"
aaa: ()String => String

      

A little more about methods versus functions: Difference between method and function in Scala

+4


source







All Articles