How to use scala type lambda - scala

With the following code,
val x: ({type X[Y] = Function1[Y, Unit]})#X = (y: Int) =>println(y)
It successfully compiles, but how could I use it? When I call it with x(1)
An compiling occurs that complains Type mismatch, Y expected: Y accutal: Int

You can't have a value of a type like ({type X[Y] = Function1[Y, Unit]})#X, just as you can't have a value of type Option or Function1. The only thing you can do with it is to apply it to a parameter, or to use it as a type argument for another type/method, which will eventually apply it to some parameters.

Related

Calling Method inside a method giving a type mismatch error Scala

So I'm trying to call a method("Mean") from inside another method("Centre"), it's giving a type mismatch error.
But if I execute the method("Mean") seperately and store it's result in some variable and then execute method("Centre") using the variable instead of method("Mean"), it works.
Can anyone please explain why?
val X = Vector(3.0,4,5)
val Y = Vector(6,9.0,15)
type D = Double
type V = Vector[D]
def Mean (v:V)= v.sum/v.length
val meanX = Mean(X)
def Centre (v:V) = v.map(X => X - Mean(X))
Centre(X)
Error:
command-1723108043672149:8: error: type mismatch;
found : D
(which expands to) Double
required: V
(which expands to) scala.collection.immutable.Vector[Double]
def Centre (v:V) = v.map(X => X - Mean(X))
but it works if I use "meanX" instead of "Mean(X):
Centre: (v: V)scala.collection.immutable.Vector[Double]
res36: scala.collection.immutable.Vector[Double] = Vector(-1.0, 0.0,1.0)
Mean() is defined to take an argument of type V (i.e. Vector[Double]) but in this code, v.map(X => X - Mean(X)) you're trying to pass a Double value instead, because you have redefined the variable X. Thus the error.
I think what you want to do is v.map(n => n - Mean(X)) or, better yet, v.map(_ - Mean(X)). That way X has only one meaning.

Spark Scala Method Signature in DataFrame API

Hi I am trying to understand scala more and I think I am a little lost with this method signature.
explode[A <: Product](input: Column*)(f: (Row) ⇒ TraversableOnce[A])(implicit arg0: scala.reflect.api.JavaUniverse.TypeTag[A]): DataFrame
First off, what is the "<:" supposed to mean in the square brakcets? Are A and B supposed to be parameter types? But Column is the argument type.
Secondly, it looks like it does a lambda function from (Row) to Traversable[A] but I haven't seen a lambda yet that doesn't have the left side argument on the right side argument at least once.
Also, I 'm not 100 percent usre why it has the implicit arg0: piece
Thanks in advance!
what is the "<:" supposed to mean in the square brackets?
<: means subtype in scala, so here it means the A is a subtype of Product. It acts like a kind of upper bound which limits the type that can be passed here to be subtype of Product
Are A and B supposed to be parameter types? But Column is the argument
type
A is not the parameter type, it is a parameter by itself, which is called type parameter. It is a little bit confusing but basically it means you can pass any type that is a subtype of product to this position and use the type parameter inside the function. This makes the function more generic because it can handle different types at the same time and you don't have to write separate functions for different types;
it looks like it does a lambda function from (Row) to Traversable[A]
f: (row) => Traversable[A] is another parameter which in this case is a function type which accepts (row) and return Traversable[A]. By this definition, explode can accept a function as a parameter, in which case is a lambda expression;
To illustrate the last case:
def sum(x: Int, y: Int)(f: Int => Int) = f(x) + f(y)
sum: (x: Int, y: Int)(f: Int => Int)Int
sum(2,3)(x => 2*x)
res2: Int = 10
In conclusion, the function explode accepts three parameters in total, the first one A is a type parameter. The second and the third are real arguments of the function, with Input being of type Column as you have noticed and f being of type (row) => Traversable[A] which is a function type.

scala lower type bounds example

I have the following code:
class A[+X] {
def printY[Y >: X](y: Y) = println(y)
}
class F
class G extends F
val f = new F
val g = new G
val a = new A[F]
a.printY(g)
I expect a compilation error in a.printY(g) as g has type G which is not a supertype of F. But in class A I indicated that printY method only accepts supertype of A's type paramter which is F in my example.
Why it works correctly?
Because g is also an instance of F. Therefore, Y is inferred as F, which is a supertype of F. I.e.:
a.printY[F](g)
However, this wouldn't compile:
a.printY[G](g)
Note: if you want a.printY(g) not to compile you need to rewrite the method:
def printY[Y](y: Y)(implicit ev: X <:< Y) = println(y)
This way the compiler infers the type parameter to be G and then checks whether it's a supertype of F instead of looking for a supertype of F which also happens to be an acceptable type for g.
Just try to explain why it works from another two angles.
First, as you know the upper bound is reflexive, for Y >: X, type X or subtype of Y is acceptable. so when you define val a = new A[F], printY will be like:
def printY[Y >: F](y: Y) = println(y)
when you invoke a.printY(g), printY's type parameter will be inferred as G, which is also a type of F.
Second, for def printY[Y >: F](y: Y) = println(y), when you pass an instance I of type Y, compiler will try to find the common parent of I and F and make the resultant type as the type parameter of printY, so you can even pass value of String, Int to printY.
a.printY[Any]("xxx")
a.printY[Any](3)

Scala: Option[T] as ?[T] (or even T?)

i tried
type ?[_] = Option[_]
def f(x: ?[Int]) = for (y <- x) yield y
(but i don't know what i am doing.)
insofar as types are just objects, i should be able to define a postix operator (i.e. zero arity method) for use in type signatures (i think). it might need a space like
def f(x: Int ?) = for (y <- x) yield y
scala makes it easy to use the Option type with matching and polymorphism, avoid null. but, most classes are (nullable) vars and java often returns vars. using classes and calling java are two of scala's selling points. an easy-to-write and easy-to-read syntax would support Options even more strongly.
what are all the things that scala does with "?" that make its parsing special.
ideally, one could write
def f(x: Int?) = for (y <- x) yield y
like other languages. can we do this in scala (without a macro)?
First, types are not objects. In fact, Scala has exactly two namespaces: values and types. They are very different things, and play by very different rules.
The postfix idea is kind of nice, actually, but it is not possible. There's an infix notation for types, though.
Now, to what you wrote:
type ?[_] = Option[_]
Each underscore has a different meaning. The underscore in ?[_] means ? is higher-kinded, but you don't care what it's type parameter is. The underscore in Option[_] means Option is an existential type. So when you write x: ?[Int], Scala will convert it to x: Option[t] { forSome type t }. This means that not only you don't get the Int, but the type parameter of Option is unknowable (you just know it exists).
However, it does compile:
scala> def f(x: ?[Int]) = for (y <- x) yield y
f: (x: ?[Int])Option[Any]
Which version of Scala did you use? 2.11? A co-worker of mine has already found some type inference regressions on 2.11, so that could be it.
The proper way to write the type alias would be this:
type ?[+A] = Option[A]
Not only we pass the type parameter along (it is a parameter, after all!), but we need to specify co-variance for it to act just Option (which is co-variant itself).
Now, as to your two questions, Scala has absolutely no special treatment of ?. And, no, you can't do this. This ? is not exactly widespread among languages either, and in all of them that support it, it is built in the language, and not something externally defined.
Besides, it's kind of a joke that, when interface with Java, typing out Option would be a problem -- not with the average identifier size in Java!
You intended to get an Option[Int] out:
scala> type ?[A] = Option[A]
defined type alias $qmark
scala> def f(x: ?[Int]) = for (y <- x) yield y + 1
f: (x: ?[Int])Option[Int]
and it does compile anyway.
You could maybe
scala> type ?[A,_] = Option[A]
defined type alias $qmark
scala> def f(x: Int ? _) = for (y <- x) yield y + 1
f: (x: ?[Int, _])Option[Int]
or similar.
scala> def f(x: Int ?_) = for (y <- x) yield y + 1
f: (x: ?[Int, _])Option[Int]
looks more postfixy.
P.S. Still curious whether variance annotation on type alias is required or merely advisable.
scala> type ?[A] = Option[A]
defined type alias $qmark
scala> trait X ; trait Y extends X ; trait Z extends X
defined trait X
defined trait Y
defined trait Z
scala> val x: ?[X] = null.asInstanceOf[?[Y]] // why is this OK?
x: ?[X] = null
scala> class C[A]
defined class C
scala> val c: C[X] = null.asInstanceOf[C[Y]] // like this is not OK
<console>:10: error: type mismatch;
found : C[Y]
required: C[X]
Note: Y <: X, but class C is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
val c: C[X] = null.asInstanceOf[C[Y]]
^
Maybe compare SI-8522 and related issues.
You might consider a renaming import. When you create a type alias you only rename a type. When you rename a symbol during import you include all referents of that name, both type and value.
To wit:
scala> import scala.{Option => ?}
import scala.{Option=>$qmark}
scala> val oi1: ?[Int] = Some(1)
oi1: Option[Int] = Some(1)
scala> def mi1(oi: ?[Int]): Int = oi.getOrElse(-1)
mi1: (oi: Option[Int])Int
scala> mi1(None)
res1: Int = -1
scala> mi1(?(1))
res2: Int = 1
Compare with this:
scala> type ?[A] = Option[A]
scala> def mi1(oi: ?[Int]): Int = oi.getOrElse(-1)
mi1: (oi: ?[Int])Int
scala> mi1(?(1))
<console>:10: error: not found: value ?
mi1(?(1))
^

Curried update method

I'm trying to have curried apply and update methods like this:
def apply(i: Int)(j: Int) = matrix(i)(j)
def update(i: Int, j: Int, value: Int) =
new Matrix(n, m, (x, y) => if ((i,j) == (x,y)) value else matrix(x)(y))
Apply method works correctly, but update method complains:
scala> matrix(2)(1) = 1
<console>:16: error: missing arguments for method apply in class Matrix;
follow this method with `_' if you want to treat it as a partially applied function
matrix(2)(1) = 1
Calling directly update(2)(1)(1) works, so it is a conversion to update method that doesn't work properly. Where is my mistake?
The desugaring of assignment syntax into invocations of update maps the concatenation of a single argument list on the LHS of the assignment with the value on the RHS of the assignment to the first parameter block of the update method definition, irrespective of how many other parameter blocks the update method definition has. Whilst this transformation in a sense splits a single parameter block into two (one on the LHS, one on the RHS of the assignment), it will not further split the left parameter block in the way that you want.
I also think you're mistaken about the example of the explicit invocation of update that you show. This doesn't compile with the definition of update that you've given,
scala> class Matrix { def update(i: Int, j: Int, value: Int) = (i, j, value) }
defined class Matrix
scala> val m = new Matrix
m: Matrix = Matrix#37176bc4
scala> m.update(1)(2)(3)
<console>:10: error: not enough arguments for method update: (i: Int, j: Int, value: Int)(Int, Int, Int).
Unspecified value parameters j, value.
m.update(1)(2)(3)
^
I suspect that during your experimentation you actually defined update like so,
scala> class Matrix { def update(i: Int)(j: Int)(value: Int) = (i, j, value) }
defined class Matrix
The update desugaring does apply to this definition, but probably not in the way that you expect: as described above, it only applies to the first argument list, which leads to constructs like,
scala> val m = new Matrix
m: Matrix = Matrix#39741f43
scala> (m() = 1)(2)(3)
res0: (Int, Int, Int) = (1,2,3)
Here the initial one-place parameter block is split to an empty parameter block on the LHS of the assignment (ie. the ()) and a one argument parameter block on the RHS (ie. the 1). The remainder of the parameter blocks from the original definition then follow.
If you're surprised by this behaviour you won't be the first.
The syntax you're after is achievable via a slightly different route,
scala> class Matrix {
| class MatrixAux(i : Int) {
| def apply(j : Int) = 23
| def update(j: Int, value: Int) = (i, j, value)
| }
|
| def apply(i: Int) = new MatrixAux(i)
| }
defined class Matrix
scala> val m = new Matrix
m: Matrix = Matrix#3af30087
scala> m(1)(2) // invokes MatrixAux.apply
res0: Int = 23
scala> m(1)(2) = 3 // invokes MatrixAux.update
res1: (Int, Int, Int) = (1,2,3)
My guess is, that it is simply not supported. Probably not due to an explicit design decision, because I don't see why it shouldn't work in principle.
The translation concerned with apply, i.e., the one performed when converting m(i)(j) into m.apply(i, j) seems to be able to cope with currying. Run scala -print on your program to see the code resulting from the translation.
The translation concerned with update, on the other hand, doesn't seem to be able to cope with currying. Since the error message is missing arguments for method apply, it even looks as if the currying confuses the translator such that it tries to translate m(i)(j) = v into m.apply, but then screws up the number of required arguments. scala -print unfortunately won't help here, because the type checker terminates the translation too early.
Here is what the language specs (Scala 2.9, "6.15 Assignments") say about assignments. Since currying is not mentioned, I assume that it is not explicitly supported. I couldn't find the corresponding paragraph for apply, but I guess it is purely coincidental that currying works there.
An assignment f(args) = e with a function application to the left of
the ‘=’ operator is interpreted as f.update(args, e), i.e. the
invocation of an update function defined by f.