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).
source to share
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
source to share