How to hide implicit parameters in the middle on apply chain - scala

Reduced example:
class Factory(x : Int) {
def apply(y : Int)(z : Int) : Int = x + y + z
}
class Sample {
def get[B <% Int](x : B) = new Factory(x)
}
val s = new Sample
What I want: s.get(2)(3)(4) should output 9. What I get
error: type mismatch;
found : Int(3)
required: Int => Int
s.get(2)(3)(4)
^
It is perfectly correct, compiler fails as it should. The second parameter list should contain implicit conversion, but it is omitted. Hence the error arises.
The question is how to make the compiler know that is should perform implicit resolution.
Things I've tried that does not work:
s.get(2)()(3)(4)
{s get 2}(3)(4)
(s get 2)(3)(4)
((s get 2))(3)(4)
Explicit way works, but it requires two lines instead of one:
val b = s get 2
b(3)(4)
I could also use the apply method explicitly: s.get(2).apply(3)(4) But it looks ugly.
How can I make compiler perform implicit resolution inside an expression?

You can use an explicit type ascription
val nine = (s.get(2): Factory)(3)(4)
Or if you find this inconvenient, build your own control structure for forcing type inference:
def infer[X](z: => X): X = z
val nineAgain = infer(s get 2)(3)(4)

s.get(2)(implicitly)(3)(4)
(implicitly is just a method defined in Predef: def implicitly[A](implicit x: A) = x.)

Related

Why I can't apply just an underscore to first parameter in Scala?

I don't know why pattern d is bad in this list below.
Why need expicit type declaration?
def adder1(m:Int,n:Int) = m + n
val a = adder1(2,_) //OK
val b = adder1(_,2) //OK
def adder2(m:Int)(n:Int) = m + n
val c = adder2(2)(_) //OK
val d = adder2(_)(2) //NG:missing parameter type
val e = adder2(_:Int)(2) //OK
I just want to know the reason pattern d needs parameter type.
Very welcome just showing citation language spec.
So I believe this comes from the concept of Partial Application.
Intuitively, partial function application says "if you fix the first arguments of the function, you get a function of the remaining arguments"
...
Scala implements optional partial application with placeholder, e.g. def add(x: Int, y: Int) = {x+y}; add(1, _: Int) returns an incrementing function. Scala also support multiple parameter lists as currying, e.g. def add(x: Int)(y: Int) = {x+y}; add(1) _.
Lets take a look at adder2
From the REPL:
scala> def adder2(m:Int)(n:Int) = m + n
def adder2(m: Int)(n: Int): Int
Lets get a value to represent this:
scala> val adder2Value = adder2
^
error: missing argument list for method adder2
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `adder2 _` or `adder2(_)(_)` instead of `adder2`.
Ok, let's try:
val adder2Value = adder2 _
val adder2Value: Int => (Int => Int) = $Lambda$1382/0x0000000840703840#4b66a923
Ahha!
In English: "A function that takes an Int and returns a function that takes an Int and returns an Int"
How can we bind the second argument using this signature? How can we access the inner function unless we first have gone through the outer one?
As far as I know, this is not possible to do using this signature, unless you explicitly define the type of your first argument.
(But what about adder2(_)(_)?)
scala> adder2(_)(_)
^
error: missing parameter type for expanded function ((<x$1: error>, x$2) => adder2(x$1)(x$2))
^
error: missing parameter type for expanded function ((<x$1: error>, <x$2: error>) => adder2(x$1)(x$2))
(Maybe this hints at our solution?)
Notice what happens if we explicitly define both arguments:
val adder2Value2= adder2Value (_:Int) (_:Int)
val adder2Value2: (Int, Int) => Int = $Lambda$1394/0x000000084070d840#32f7d983
This is much more manageable, we can now fix either argument, and get a simplified partial function:
scala> val adder2FirstArg = adder2Value (_:Int) (10)
val adder2FirstArg: Int => Int = $Lambda$1395/0x000000084070d040#47f5ddf4
scala> val adder2SecondArg = adder2Value (5) (_:Int)
val adder2SecondArg: Int => Int = $Lambda$1396/0x000000084070c840#21ed7ce
So what's really going on here?
When you bind an argument to a value, you have explicitly expressed the type (maybe it's inferred, but it's definitely that type, in this case, Ints). It's sugar so we don't need to write it. But under the hood, these are composed functions, and how they are composed is very important. To be able to match and simplify the function signature, the compiler requires us to provide this information in an outside-in manner. Otherwise, we need to give it some help to get there.
EDIT:
I think that this question serves as more of a Scala language spec. puzzle exercise, however. I can't think of any good reason, from a design perspective, for which you would need to implement a curried function in such a way that you cannot order the parameters such that the last parameters are the ones being inferred.

Why is the following scala experimental code not working?

I'm trying to define a generic add function to numeric values:
def add[A](x:A, y:A): A = {
x + y
}
console:16: error: type mismatch;
found : A
required: String
x + y
^
What's the compiler complaining about?
Some of the stuff I've googled does not quite make sense to me at this moment.
Since you define A with no boundaries and no extra information, it could be any type, and not any Scala type has a + method - so this can't compile.
The error message is a result of the compiler's attempt to implicitly convert x into a String (because String has a + method, and every type can be converted to string using toString), but then it fails because y isn't a string.
To create a method for all numeric types, you can use the Numeric type:
def add[A](x:A, y:A)(implicit n: Numeric[A]): A = {
n.plus(x, y)
}
add(1, 3)
add(1.4, 3.5)
EDIT: or an equivalent syntax:
def add[A: Numeric](x:A, y:A): A = {
implicitly[Numeric[A]].plus(x, y)
}
To be able to do something like this the compiler needs to know that A has a method
def +(a: A): A
so ideally you would want to do something like
def add[A :< Numeric](x:A, y:A): A = { ...
but you can't because the numeric types in Scala have no common super type (they extend AnyVal). Look here for a related question.

Self-referential duck-typing

I wish to write a function that operates on any value that can be added to other members of its own type (whatever "added" means in context). The obvious (heh-heh) definition of such a type:
type Addable = { def +(a : Addable) : Addable }
That gives me an error I don't understand at all: recursive method + needs result type
Why isn't that last : Addable the result type? Why does it think + is recursive anyway?
But I found a more general problem, trying to refer to a type inside its own definition:
type T = { def f: T }
But then I had a brain-wave: solve it the way I would in Java!
type T[T] = { def f: T }
This compiled!
But now I have two more problems.
First, I have no idea how to use type T. In particular,
def n(a:T) = a.f
gives the wholly sensible yet frustrating "type T takes type parameters" error.
Second, attempting to apply this pattern to the original problem
type Addable[Addable] = { def +(a : Addable) : Addable }
leads to a completely incomprehensible "Parameter type in structural refinement may not refer to an abstract type defined outside that refinement". (The actual problem is not that it's "+" -- thank God and Martin, since that would complete mess up my head -- just that it takes an Addable as a parameter.)
So
How do I define a duck-type meaning "has a particular function returning a value of the same type"?
How do I define a duck-type meaning "has a particular function taking a expression of the same type as a parameter"?
I have a religious-like belief that this problem is solvable.
Those are different Ts.
scala> type T[T] = { def f: T }
defined type alias T
scala> var x: T[Int] = null
x: T[Int] = null
scala> x = new AnyRef { def f = 5 }
x: T[Int] = $anon$1#44daa9f1
When you write:
type Addable[Addable] = { def +(a : Addable) : Addable }
You have a type Addable which takes a single type parameter, also called Addable. Here's a similar variation people often confuse themselves with.
scala> def f[Int](x: Int) = x * x
<console>:7: error: value * is not a member of type parameter Int
def f[Int](x: Int) = x * x
^
The actual answer to your question is "you can't" but I would hate to shatter your religious-like faith so instead I'll say "structural types work in mysterious ways." If you want to go on a religious mission you might visit here, which explains why you can't.
http://article.gmane.org/gmane.comp.lang.scala/7013

Scala compiler not recognizing a view bound

I've tried this line of code
def **[A <% Numeric[A]](l:List[A],m:List[A])=l.zip(m).map({t=>t._1*t._2})
However on compilation, I get this error
error: value * is not a member of type parameter A
def **[A <% Numeric[A]](l:List[A],m:List[A])=l.zip(m).map({t=>t._1*t._2})
When I look at the source for the Numeric trait, I see a * op defined.
What am I doing wrong?
The instance of Numeric is not a number itself, but it is an object that offers operations to do the arithmetic. For example, an object num of type Numeric[Int] can add two integers like this: num.plus(3, 5) The result of this operation is the integer 7.
For integers, this is very trivial. However, for all basic numerical types, there is one implicit instance of Numeric available. And if you define your own numeric types, you can provide one.
Therefore, you should leave the bounds for A open and add an implicit parameter of type Numeric[A], with which you do the calculations. Like this:
def **[A](l:List[A],m:List[A])(implicit num:Numeric[A])=l.zip(m).map({t=>num.times(t._1, t._2)})
Of course, num.times(a,b) looks less elegant than a*b. In most of the cases, one can live with that. However, you can wrap the value a in an object of type Ops that supports operators, like this:
// given are: num:Numeric[A], a:A and b:A
val a_ops = num.mkNumericOps(a)
val product = a_ops * b
Since the method mkNumericOps is declared implicit, you can also import it and use it implicitly:
// given are: num:Numeric[A], a:A and b:A
import num._
val product = a * b
You can also solve this with a context bound. Using the context method from this answer, you can write:
def **[A : Numeric](l:List[A],m:List[A]) =
l zip m map { t => context[A]().times(t._1, t._2) }
or
def **[A : Numeric](l:List[A],m:List[A]) = {
val num = context[A]()
import num._
l zip m map { t => t._1 * t._2 }
}

Can Scala allow free Type Parameters in arguments (are Scala Type Parameters first class citizens?)?

I have some Scala code that does something nifty with two different versions of a type-parameterized function. I have simplified this down a lot from my application but in the end my code full of calls of the form w(f[Int],f[Double]) where w() is my magic method. I would love to have a more magic method like z(f) = w(f[Int],f[Double]) - but I can't get any syntax like z(f[Z]:Z->Z) to work as it looks (to me) like function arguments can not have their own type parameters. Here is the problem as a Scala code snippet.
Any ideas? A macro could do it, but I don't think those are part of Scala.
object TypeExample {
def main(args: Array[String]):Unit = {
def f[X](x:X):X = x // parameterize fn
def v(f:Int=>Int):Unit = { } // function that operates on an Int to Int function
v(f) // applied, types correct
v(f[Int]) // appplied, types correct
def w[Z](f:Z=>Z,g:Double=>Double):Unit = {} // function that operates on two functions
w(f[Int],f[Double]) // works
// want something like this: def z[Z](f[Z]:Z=>Z) = w(f[Int],f[Double])
// a type parameterized function that takes a single type-parameterized function as an
// argument and then speicalizes the the argument-function to two different types,
// i.e. a single-argument version of w() (or wrapper)
}
}
You can do it like this:
trait Forall {
def f[Z] : Z=>Z
}
def z(u : Forall) = w(u.f[Int], u.f[Double])
Or using structural types:
def z(u : {def f[Z] : Z=>Z}) = w(u.f[Int], u.f[Double])
But this will be slower than the first version, since it uses reflection.
EDIT: This is how you use the second version:
scala> object f1 {def f[Z] : Z=>Z = x => x}
defined module f1
scala> def z(u : {def f[Z] : Z=>Z}) = (u.f[Int](0), u.f[Double](0.0))
z: (AnyRef{def f[Z]: (Z) => Z})(Int, Double)
scala> z(f1)
res0: (Int, Double) = (0,0.0)
For the first version add f1 extends Forall or simply
scala> z(new Forall{def f[Z] : Z=>Z = x => x})
If you're curious, what you're talking about here is called "rank-k polymorphism." See wikipedia. In your case, k = 2. Some translating:
When you write
f[X](x : X) : X = ...
then you're saying that f has type "forall X.X -> X"
What you want for z is type "(forall Z.Z -> Z) -> Unit". That extra pair of parenthesis is a big difference. In terms of the wikipedia article it puts the forall qualifier before 2 arrows instead of just 1. The type variable can't be instantiated just once and carried through, it potentially has to be instantiated to many different types. (Here "instantiation" doesn't mean object construction, it means assigning a type to a type variable for type checking).
As alexy_r's answer shows this is encodable in Scala using objects rather than straight function types, essentially using classes/traits as the parens. Although he seems to have left you hanging a bit in terms of plugging it into your original code, so here it is:
// this is your code
object TypeExample {
def main(args: Array[String]):Unit = {
def f[X](x:X):X = x // parameterize fn
def v(f:Int=>Int):Unit = { } // function that operates on an Int to Int function
v(f) // applied, types correct
v(f[Int]) // appplied, types correct
def w[Z](f:Z=>Z,g:Double=>Double):Unit = {} // function that operates on two functions
w(f[Int],f[Double]) // works
// This is new code
trait ForAll {
def g[X](x : X) : X
}
def z(forall : ForAll) = w(forall.g[Int], forall.g[Double])
z(new ForAll{def g[X](x : X) = f(x)})
}
}
I don't think what you want to do is possible.
Edit:
My previous version was flawed. This does work:
scala> def z(f: Int => Int, g: Double => Double) = w(f, g)
z: (f: (Int) => Int,g: (Double) => Double)Unit
scala> z(f, f)
But, of course, it is pretty much what you have.
I do not think it is even possible for it to work, because type parameters exist only at compile-time. At run time there is no such thing. So it doesn't make even sense to me to pass a parameterized function, instead of a function with the type parameters inferred by Scala.
And, no, Scala has no macro system.