|
View:
New views
13 Messages
—
Rating Filter:
Alert me
|
|
|
[scala] Numerics and implicitsLet's say you want to create a function that works on all numeric types.
We want nice syntax, so we define a wrapper class: case class Num[T](v : T)(implicit n : Numeric[T]) { def +(v2 : T) = n.plus(v, v2) def *(v2 : T) = n.times(v, v2) } implicit def numericToNum[T : Numeric](v : T) = Num(v) Now let's try it: scala> def calc[T : Num](v1 : T, v2 : T) : T = v1 + v2 <console>:7: error: type mismatch; found : T required: ?{val +: ?} Note that implicit conversions are not applicable because they are ambiguous: both method numericToNum in object $iw of type [T](v: T)(implicit evidence$1: Numeric[T])Num[T] and method any2stringadd in object Predef of type (x: Any)scala.runtime.StringAdd are possible conversion functions from T to ?{val +: ?} def calc[T : Num](v1 : T, v2 : T) : T = v1 + v2 ^ Ouch, this is really bad. The problem has three components: - The implicit "Any => StringAdd" conversion in Predef. Could probably be changed to "String => StringAdd" without breaking too many apps. - "T => Num[T]" is not considered more specific than "Any => StringAdd" by the compiler. - An implicit conversion in an inner scope is not prioritized over a conversion in an outer scope. What can be done to solve this problem? /Jesper Nordenberg |
|
|
[scala] Re: Numerics and implicitsJesper Nordenberg wrote:
> scala> def calc[T : Num](v1 : T, v2 : T) : T = v1 + v2 Should be: def calc[T : Numeric](v1 : T, v2 : T) : T = v1 + v2 but that doesn't affect the problem. One solution is to unimport any2stringadd, "import scala.Predef.{any2stringadd => _}" (thanks, Ricky), but that has obvious drawbacks. /Jesper Nordenberg |
|
|
Re: [scala] Numerics and implicits2009/10/14 Jesper Nordenberg <megagurka@...>:
> [...] > Ouch, this is really bad. The problem has three components: > > - The implicit "Any => StringAdd" conversion in Predef. Could probably be > changed to "String => StringAdd" without breaking too many apps. > [...] Hello, if the implicit conversion to StringAdd is not applicable to any value, it is pretty useless. As far as I can see it is mostly useful to make the plus operator on strings and other values commutative; without the conversion from Any to StringAdd something like val str = 42 + "foo" would not be legal. However, it should be possible to disable the conversion for compilation units where it gets in your way using import Predef.{ any2stringadd => _ } Ciao, Thomas -- When C++ is your hammer, every problem looks like your thumb. |
|
|
[scala] Re: Numerics and implicitsThomas Chust wrote:
> if the implicit conversion to StringAdd is not applicable to any > value, it is pretty useless. I disagree. For example: "1 + 1: " + 2 + ", 1 == 2: " + false would still work fine. > As far as I can see it is mostly useful > to make the plus operator on strings and other values commutative; String concatenation isn't commutative (so the choice of the + operator is not optimal, but that's another discussion). /Jesper Nordenberg |
|
|
Re: [scala] Re: Numerics and implicits+1 I'd rather write val s = "" + 42 + " answer" instead of having to fight to get my implicit conversions working because of that StringAdd-Predef-Thingy. My 2c... Daniel |
|
|
Re: [scala] Re: Numerics and implicitsOn Wed, 2009-10-14 at 08:17 -0700, Landei wrote:
> +1 > > I'd rather write val s = "" + 42 + " answer" instead of having to fight to > get my implicit conversions working because of that StringAdd-Predef-Thingy. Indeed. It would probably break quite a bit of code, but this is probably the last change for something like that (if not too late already). Best, Ismael |
|
|
Re: [scala] Re: Numerics and implicitsOn Wed, Oct 14, 2009 at 05:02:16PM +0100, Ismael Juma wrote:
> Indeed. It would probably break quite a bit of code, but this is > probably the last change for something like that (if not too late > already). I also would love to get rid of any2stringadd, although the general problem of the degree of imposition imposed by Predef (and library implicits in general -- as pointed out by retronym there is no real way to work around those defined in a companion object) remains. Still, one has to start somewhere and any implicit which operates on "Any" had better come with a free trip to Bermuda. -- Paul Phillips | Beware of bugs in the above code; I have only Apatheist | proved it correct, not tried it. Empiricist | -- Knuth i'll ship a pulp |----------* http://www.improving.org/paulp/ *---------- |
|
|
Re: [scala] Re: Numerics and implicits2009/10/14 Jesper Nordenberg <megagurka@...>:
> Thomas Chust wrote: >> >> if the implicit conversion to StringAdd is not applicable to any >> value, it is pretty useless. > > I disagree. For example: > > "1 + 1: " + 2 + ", 1 == 2: " + false > > would still work fine. > [...] Hello, of course, but that's completely beside the point, since for that to work, no implicit conversion is needed at all: The plus method on strings can just accept any argument. I didn't say the conversion from Any to StringAdd was necessary to convert something into a string, but if the conversion to StringAdd was present at all and its source type wasn't Any, then it could just as well be omitted completely -- it would serve no purpose and be unnecessary ballast. That said, I *do* like the fact that the string concatenation operator in Scala is symmetric[1], accepting any type of argument on either side and automatically converting it into a string, as long as at least one of the arguments is already a string. Therefore I don't think the any2stringadd implicit should be removed. Personally I would have chosen a different name for the concatenation operator, for example the binary "++" already used to mean concatenation for any other type of sequence or maybe a binary "~", but that design decision is most unlikely to change now. Ciao, Thomas [1] I wrote "commutative" instead of "symmetric" in my previous message by mistake :-( -- When C++ is your hammer, every problem looks like your thumb. |
|
|
Re: [scala] Re: Numerics and implicitsI agree that String + is a wart but let's be realistic. Too much code
depends on it (in general and on the fact that it's symmetric). It won't go. We just have to design around it. Cheers -- Martin On Wed, Oct 14, 2009 at 7:08 PM, Thomas Chust <chust@...> wrote: > 2009/10/14 Jesper Nordenberg <megagurka@...>: >> Thomas Chust wrote: >>> >>> if the implicit conversion to StringAdd is not applicable to any >>> value, it is pretty useless. >> >> I disagree. For example: >> >> "1 + 1: " + 2 + ", 1 == 2: " + false >> >> would still work fine. >> [...] > > Hello, > > of course, but that's completely beside the point, since for that to > work, no implicit conversion is needed at all: The plus method on > strings can just accept any argument. I didn't say the conversion from > Any to StringAdd was necessary to convert something into a string, but > if the conversion to StringAdd was present at all and its source type > wasn't Any, then it could just as well be omitted completely -- it > would serve no purpose and be unnecessary ballast. > > That said, I *do* like the fact that the string concatenation operator > in Scala is symmetric[1], accepting any type of argument on either > side and automatically converting it into a string, as long as at > least one of the arguments is already a string. Therefore I don't > think the any2stringadd implicit should be removed. Personally I would > have chosen a different name for the concatenation operator, for > example the binary "++" already used to mean concatenation for any > other type of sequence or maybe a binary "~", but that design decision > is most unlikely to change now. > > Ciao, > Thomas > > > [1] I wrote "commutative" instead of "symmetric" in my previous > message by mistake :-( > > > -- > When C++ is your hammer, every problem looks like your thumb. > |
|
|
[scala] Re: Numerics and implicitsJesper Nordenberg wrote:
> implicit def numericToNum[T : Numeric](v : T) = Num(v) > scala> def calc[T : Num](v1 : T, v2 : T) : T = v1 + v2 What do [T : Numeric] and [T : Num] mean? Why does the compiler consider any2stringadd, given the second argument to + is not a String? Note that the following compiles:- implicit def numericToNum[T <: Numeric[T]] (v : T)(implicit n : Numeric[T]) = Num(v) def calc[T <: Num[T]](v1 : T, v2 : T) : T = v1 + v2 A small variation also compiles with the latest nightly build:- implicit def numericToNum[T <: Numeric[_]] (v : T)(implicit n : Numeric[T]) = Num(v) def calc[T <: Num[_]](v1 : T, v2 : T) : T = v1 + v2 although it failed with some September nightly builds: error: type mismatch; found : T required: _$2 where type _$2 def calc[T <: Num[_]](v1 : T, v2 : T) : T = v1 + v2 ^ |
|
|
[scala] Re: Numerics and implicitsEric Willigers wrote:
> A small variation also compiles with the latest nightly build:- Correction: it also fails with the latest nightly build. Sorry for the spam. |
|
|
Re: [scala] Re: Numerics and implicitsI can get this to compile with the latest nightly:
implicit def numericOps[T : Numeric](x: T): Numeric[T]#Ops = implicitly[Numeric[T]].mkNumericOps(x) def foo[T <% Numeric[T]#Ops](x: T, y: T): T = x + y If I try to leave out the result type on "foo" it complains with "error: recursive method foo needs result type", which is pretty mind-boggling. --j On Wed, Oct 14, 2009 at 4:40 PM, Eric Willigers <ewilligers@...> wrote:
|
|
|
Re: [scala] Re: Numerics and implicitsOn Thu, Oct 15, 2009 at 1:29 AM, Eric Willigers <ewilligers@...> wrote: they're context bounds. [T : B] desugars to an implicit argument list (implicit evidence: B[T])What do [T : Numeric] and [T : Num] mean? they generalise view bounds: [T <% V] can be recovered as [T : ToV]
with a type alias type ToV[X] = X => V[X] adriaan
|
| Free embeddable forum powered by Nabble | Forum Help |