type parameters and numeric widening - scala

As we know, we can add (subtract/multiply/etc.) two numbers of different Numeric types and the result will be the wider of the two types, regardless of their order.
33F + 9L // Float + Long == Float
33L + 9F // Long + Float == Float
This is because each of the 7 Numeric classes (Byte, Short, Char, Int, Long, Float, Double) has 7 different +() methods (and -(), *(), etc), one for every Numeric type that can be received as a passed parameter. [There's an extra +() method for handling a String parameter, but that need not concern us here.]
Now consider the following:
implicit class PlusOrMinus[T: Numeric](a: T) {
import Numeric.Implicits._
def +-(b: T) = if (util.Random.nextBoolean) a+b else a-b
}
This works if the two operands are the same type, but it also works if the type of the 1st operand is wider than the type of the 2nd.
11F +- 2L // result: Float = 9.0 or 13.0
I believe what's happening here is that the compiler uses weak conformance to achieve numeric widening on the 2nd operand (the b parameter) as it is passed to the +-() method.
But the 1st operand won't be widened to match the 2nd. It won't even compile.
11L +- 2F // Error: type mismatch; found: Float(2.0) required: Long
Is there any way around this limitatiion?
I can't use a different type parameter for the b argument (def +-[U: Numeric](b: U) = ...) because a Numeric, expressed via a type parameter, can only add/subtract it's own type.
Is the only solution to create 7 different classes (PlusOrMinusShort/Int/Long/etc.) with 7 different methods (def +-(b:Short), def +-(b:Int), def +-(b:Long), etc.)?

Here is a way:
implicit class PlusOrMinus[T: Numeric](a: T) {
import Numeric.Implicits._
def +-(b: T) = plusOrMinus(a,b)
def +-[U: Numeric](b: U)(implicit ev: T => U) = plusOrMinus[U](a,b)
private def plusOrMinus[W: Numeric](a: W, b: W): W =
if (util.Random.nextBoolean) a+b else a-b
}
Then, with this, I get the following interaction:
scala> 11F +- 2L
res0: Float = 9.0
scala> 11L +- 2F
res1: Float = 9.0
The idea is that if I could just have a function plusOrMinus, this whole problem would be trivial, since the same widening could happen for either arguments. After defining such a function, the problem becomes how to embed it into an implicit class to use it in an infix form.
Here, we have only two cases: either the second argument needs to be widened or the argument wrapped by the implicit class needs to be widened. The first of these cases is covered by the first +- method (for the reasons you observed above). For the second, however, we need to explicitly say that there is some conversion that is possible and pass the generic type of the conversion to plusOrMinus.

Related

Scala add value to a char variable

I am creating a simple function in Scala
def addOne(m: Int): Int = m + 1
Using it with integers works normally, using double it throws a type mismatch error.
addOne(2) = 3
addOne(2.1) = error: type mismatch
When I use it with a character in double quotes, it throws a type mismatch as expected.
addOne("z") = error: type mismatch
However, when using a single quotes character it returns a value for that letter.
addOne('z') = 123
What is happening here and why is it like this?
The reason you can use a Char as an argument to a function taking an Int is because Scala performs an implicit conversion from Char to Int. This specific conversion is defined in the companion object of the Char class. See here:
http://www.scala-lang.org/api/2.12.1/scala/Char$.html (It seems like SO breaks this link at the $ character. Copy-paste it instead)
The function perfoming the conversion is called char2int. It converts the Char into its corresponding Unicode value as an Int.
When the Scala compiler sees that the types Char and Int don't match, it will first check if there are any available implicit conversions. It only gives a compile error if it didn't find any. If it finds an implicit conversion, it will insert that function call into your code. Your code is therefore transformed to this:
addOne(Char.char2int('z'))
If you want to make your own implicit conversion to, for example, let your function accept String, you can define this:
// Enable implicit conversions.
import scala.language.implicitConversions
// The "implicit" modifier is the important part here, not the name of the function.
implicit def string2int(s: String) = s.toInt
Now this compiles:
// This returns 6
addOne("5")
/*
* This throws a NumberFormatException due to my implementation of string2int.
* Create your own implementation of string2int if you want it to work properly.
*/
addOne("a")
Finally: Beware that implicit conversions are very powerful and therefore can be dangerous! See TheArchetypalPaul's comment for an explanation.
It is because addOne(m: Int) [The part after colon (:) ] tells Scala you will pass Int to it, not Double, not anything else.
if you want it to work for Double, try this, but then you will always get Double as Result.
def addone (m : Double ) = m+1
addone: (m: Double)Double
scala> addone(1)
res0: Double = 2.0
scala> addone(1.1)
res1: Double = 2.1
Scala map the char type using the ASCII Table. So, 'z' is mapped to 122, which is an integer. In the method, addOne('z'), the input parameter been cast to an integer (i.e. 122).
However, the input parameter in addOne(2.1) is 2.1, which is a double and in addOne("z") is a string. They cannot be cast to an integer automatically.
def addOne(m: Int): Int = m + 1 only accept an integer for m
It also work with a single quoted character (z) because it's translated into its ASCII value. The value for 'z' is 122 and you add 1.
scala> val foo: Int = 'z'
foo: Int = 122
scala> val bar = foo + 1
bar: Int = 123
If you want to make this working with double you can specify def addOne(m: Double): Double = m + 1

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.

Scala applying implicit functions to a collection

EDIT: I'm using Scala 2.9.2
In Scala, I've defined a custom class which wraps a Double:
class DoubleWrap( d : Double ) {
def double( ) = d * 2
}
and an implicit conversion from Double to DoubleWrap:
implicit def wrapDouble( d : Double ) = new DoubleWrap( d )
This allows me to do the following:
scala> 2.5.double
res0: Double = 5.0
However, since there is an implicit conversion in Scala from Int to Double, I can also do the following:
scala> 2.double
res1: Double = 4.0
This operator can also be applied to all elements of a double-type collection using map
scala> List( 1.0, 2.0, 3.0 ).map( _.double )
res2: List[Double] = List(2.0, 4.0, 6.0)
However, if I attempt to apply the function to all elements of an integer collection, it doesn't work:
scala> List( 1, 2, 3 ).map( _.double )
<console>:10: error: value double is not a member of Int
List( 1, 2, 3 ).map( _.double )
Does anyone know why this is the case?
In scala, implicit conversions are not automatically chained. In other words, the compiler will look for a single implicit conversion that will allow the code to make sense, it will never try to apply two (or more) successive implicit conversions.
In your example, the fact that you can do 2.double has nothing to do with the fact that there is an implicit conversion from Double to Int in Predef.
As a proof, try this in the REPL:
scala> val i: Int = 2
i: Int = 2
scala> i.double
<console>:13: error: value double is not a member of Int
i.double
It does not compile.
So why does 2.double compile? Good question.
I thought I understood this intuitively: 2 can be interpreted as the Int value 2 or as the Double value 2.0 in the first place, so my intuition was that 2 is somehow already a Double in this context.
However, I think this is wrong, because even the following will compile, surpisingly: (2:Int).double (or even more strange: ((1+1):Int).double). I'll be honest, I am flabbergasted and have no idea why this compiles while val i: Int = 2; i.double does not.
So to sum up, it is normal that scala does not try to apply two implicit conversions at the same time, but for some reason this rule does not seem to apply to constant expressions.
And now for a way to fix your issue: simply modify your implicit conversion so that it accepts any type that is itself implicitly convertible to Double. In effect, this allows to chain the implicit conversions:
implicit def wrapDouble[T <% Double]( d : T ) = new DoubleWrap( d )
It's a bug which should soon be fixed.

How does one write the Pythagoras Theorem in Scala?

The square of the hypotenuse of a right triangle is equal to the sum of the squares on the other two sides.
This is Pythagoras's Theorem. A function to calculate the hypotenuse based on the length "a" and "b" of it's sides would return sqrt(a * a + b * b).
The question is, how would you define such a function in Scala in such a way that it could be used with any type implementing the appropriate methods?
For context, imagine a whole library of math theorems you want to use with Int, Double, Int-Rational, Double-Rational, BigInt or BigInt-Rational types depending on what you are doing, and the speed, precision, accuracy and range requirements.
This only works on Scala 2.8, but it does work:
scala> def pythagoras[T](a: T, b: T, sqrt: T => T)(implicit n: Numeric[T]) = {
| import n.mkNumericOps
| sqrt(a*a + b*b)
| }
pythagoras: [T](a: T,b: T,sqrt: (T) => T)(implicit n: Numeric[T])T
scala> def intSqrt(n: Int) = Math.sqrt(n).toInt
intSqrt: (n: Int)Int
scala> pythagoras(3,4, intSqrt)
res0: Int = 5
More generally speaking, the trait Numeric is effectively a reference on how to solve this type of problem. See also Ordering.
The most obvious way:
type Num = {
def +(a: Num): Num
def *(a: Num): Num
}
def pyth[A <: Num](a: A, b: A)(sqrt: A=>A) = sqrt(a * a + b * b)
// usage
pyth(3, 4)(Math.sqrt)
This is horrible for many reasons. First, we have the problem of the recursive type, Num. This is only allowed if you compile this code with the -Xrecursive option set to some integer value (5 is probably more than sufficient for numbers). Second, the type Num is structural, which means that any usage of the members it defines will be compiled into corresponding reflective invocations. Putting it mildly, this version of pyth is obscenely inefficient, running on the order of several hundred thousand times slower than a conventional implementation. There's no way around the structural type though if you want to define pyth for any type which defines +, * and for which there exists a sqrt function.
Finally, we come to the most fundamental issue: it's over-complicated. Why bother implementing the function in this way? Practically speaking, the only types it will ever need to apply to are real Scala numbers. Thus, it's easiest just to do the following:
def pyth(a: Double, b: Double) = Math.sqrt(a * a + b * b)
All problems solved! This function is usable on values of type Double, Int, Float, even odd ones like Short thanks to the marvels of implicit conversion. While it is true that this function is technically less flexible than our structurally-typed version, it is vastly more efficient and eminently more readable. We may have lost the ability to calculate the Pythagrean theorem for unforeseen types defining + and *, but I don't think you're going to miss that ability.
Some thoughts on Daniel's answer:
I've experimented to generalize Numeric to Real, which would be more appropriate for this function to provide the sqrt function. This would result in:
def pythagoras[T](a: T, b: T)(implicit n: Real[T]) = {
import n.mkNumericOps
(a*a + b*b).sqrt
}
It is tricky, but possible, to use literal numbers in such generic functions.
def pythagoras[T](a: T, b: T)(sqrt: (T => T))(implicit n: Numeric[T]) = {
import n.mkNumericOps
implicit val fromInt = n.fromInt _
//1 * sqrt(a*a + b*b) Not Possible!
sqrt(a*a + b*b) * 1 // Possible
}
Type inference works better if the sqrt is passed in a second parameter list.
Parameters a and b would be passed as Objects, but #specialized could fix this. Unfortuantely there will still be some overhead in the math operations.
You can almost do without the import of mkNumericOps. I got frustratringly close!
There is a method in java.lang.Math:
public static double hypot (double x, double y)
for which the javadocs asserts:
Returns sqrt(x2 +y2) without intermediate overflow or underflow.
looking into src.zip, Math.hypot uses StrictMath, which is a native Method:
public static native double hypot(double x, double y);