This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Units of Measurement — Scala Macros to the rescue?

52 replies
Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Hi everyone,

as some people know, I have been working on the Units of Measurement functionality of metascala, where a unit is represented by a numerical value for quantity and 7 generic types representing the SI units.

The last two major things missing in my book are implementations of toString, equals and probably hashCode. They are currently not really implementable, because they depend on the generic types which are not available at runtime.

Would macros enable me to implement these operations by looking at them at compile time? E.g. implementing equals by checking that the two compared instances have the same generic types with a macro and refusing to compile if they don't?

Thanks and bye,


Simon
dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Fri, Feb 3, 2012 at 15:50, Simon Ochsenreither
wrote:
> Hi everyone,
>
> as some people know, I have been working on the Units of Measurement
> functionality of metascala, where a unit is represented by a numerical value
> for quantity and 7 generic types representing the SI units.
>
> The last two major things missing in my book are implementations of
> toString, equals and probably hashCode. They are currently not really
> implementable, because they depend on the generic types which are not
> available at runtime.
>
> Would macros enable me to implement these operations by looking at them at
> compile time? E.g. implementing equals by checking that the two compared
> instances have the same generic types with a macro and refusing to compile
> if they don't?

That's not the semantics of ==. The == method never fails to compile

geoff
Joined: 2008-08-20,
User offline. Last seen 1 year 25 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Fri, Feb 03, 2012 at 09:50:52AM -0800, Simon Ochsenreither said
> Hi everyone,
>
> as some people know, I have been working on the Units of Measurement
> functionality of metascala, where a unit is represented by a numerical
> value for quantity and 7 generic types representing the SI units.
>
> The last two major things missing in my book are implementations of
> toString, equals and probably hashCode. They are currently not really
> implementable, because they depend on the generic types which are not
> available at runtime.

I think it should be possible to get enough information at runtime by
reification through an implicit parameter for Quantity. I think that
it'd better to and add a typesafe equality operator for Quantity instead
of trying to make use of equals a compiler error.

A sketch:

type UV[T] = TypeToValue[T, Int]

class UnitRep
[M <: MInt : UV, KG <: MInt : UV, S <: MInt : UV, A <: MInt : UV, K <:
MInt : UV, Mol <: MInt : UV, CD <: MInt : UV] {
def v[T : UV] = to[T, Int]
def rep = {
val u = List(("m",v[M]),("kg",v[KG]),("s",v[S]),("A",v[A]),
("K",v[K]),("mol",v[Mol]),("cd",v[CD]))
u.map {
case (u,0) => ""
case (u,1) => "*"+u
case (u,-1) => "/"+u
case (u,x) if x > 1 => "*%s^%d".format(u,x)
case (u,x) if x < 1 => "/%s^%d".format(u,-x)
} mkString "" drop 1
}
}

Jesper Nordenberg
Joined: 2008-12-27,
User offline. Last seen 42 years 45 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?

The problem with this approach would be that, unless some caching scheme
is implemented, a new instance of UnitRep would be created for each
Quantity instance. This would be a huge memory overhead.

/Jesper Nordenberg

Geoff Reedy skrev 2012-02-03 23:08:
> On Fri, Feb 03, 2012 at 09:50:52AM -0800, Simon Ochsenreither said
>> Hi everyone,
>>
>> as some people know, I have been working on the Units of Measurement
>> functionality of metascala, where a unit is represented by a numerical
>> value for quantity and 7 generic types representing the SI units.
>>
>> The last two major things missing in my book are implementations of
>> toString, equals and probably hashCode. They are currently not really
>> implementable, because they depend on the generic types which are not
>> available at runtime.
>
> I think it should be possible to get enough information at runtime by
> reification through an implicit parameter for Quantity. I think that
> it'd better to and add a typesafe equality operator for Quantity instead
> of trying to make use of equals a compiler error.
>
> A sketch:
>
> type UV[T] = TypeToValue[T, Int]
>
> class UnitRep
> [M<: MInt : UV, KG<: MInt : UV, S<: MInt : UV, A<: MInt : UV, K<:
> MInt : UV, Mol<: MInt : UV, CD<: MInt : UV] {
> def v[T : UV] = to[T, Int]
> def rep = {
> val u = List(("m",v[M]),("kg",v[KG]),("s",v[S]),("A",v[A]),
> ("K",v[K]),("mol",v[Mol]),("cd",v[CD]))
> u.map {
> case (u,0) => ""
> case (u,1) => "*"+u
> case (u,-1) => "/"+u
> case (u,x) if x> 1 => "*%s^%d".format(u,x)
> case (u,x) if x< 1 => "/%s^%d".format(u,-x)
> } mkString "" drop 1
> }
> }
>

geoff
Joined: 2008-08-20,
User offline. Last seen 1 year 25 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?

Good point. I bet you could do something clever with Miles' unboxed tagged types so that Quantity takes implicit Int @ M, Int @ KG, etc. and then there's only the overhead of 7 int fields and maybe no object creation during the implicit resolution.

On Feb 4, 2012, at 1:12 AM, Jesper Nordenberg wrote:

> The problem with this approach would be that, unless some caching scheme is implemented, a new instance of UnitRep would be created for each Quantity instance. This would be a huge memory overhead.
>
> /Jesper Nordenberg
>
> Geoff Reedy skrev 2012-02-03 23:08:
>> On Fri, Feb 03, 2012 at 09:50:52AM -0800, Simon Ochsenreither said
>>> Hi everyone,
>>>
>>> as some people know, I have been working on the Units of Measurement
>>> functionality of metascala, where a unit is represented by a numerical
>>> value for quantity and 7 generic types representing the SI units.
>>>
>>> The last two major things missing in my book are implementations of
>>> toString, equals and probably hashCode. They are currently not really
>>> implementable, because they depend on the generic types which are not
>>> available at runtime.
>>
>> I think it should be possible to get enough information at runtime by
>> reification through an implicit parameter for Quantity. I think that
>> it'd better to and add a typesafe equality operator for Quantity instead
>> of trying to make use of equals a compiler error.
>>
>> A sketch:
>>
>> type UV[T] = TypeToValue[T, Int]
>>
>> class UnitRep
>> [M<: MInt : UV, KG<: MInt : UV, S<: MInt : UV, A<: MInt : UV, K<:
>> MInt : UV, Mol<: MInt : UV, CD<: MInt : UV] {
>> def v[T : UV] = to[T, Int]
>> def rep = {
>> val u = List(("m",v[M]),("kg",v[KG]),("s",v[S]),("A",v[A]),
>> ("K",v[K]),("mol",v[Mol]),("cd",v[CD]))
>> u.map {
>> case (u,0) => ""
>> case (u,1) => "*"+u
>> case (u,-1) => "/"+u
>> case (u,x) if x> 1 => "*%s^%d".format(u,x)
>> case (u,x) if x< 1 => "/%s^%d".format(u,-x)
>> } mkString "" drop 1
>> }
>> }
>>
>
>

Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
Sorry, I completely disagree. Imho it is dozen times worse to have two methods where of them is just not working, because it can only compare the value, but not the types. An alternative would be to implement equals by always throwing an exception. But then I would just prefer making a known wrong equals comparison a compile time error instead.

Hashcode has the same problem, it should also be based on the value and the unit, but only the value is available at runtime.
dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Sat, Feb 4, 2012 at 09:16, Simon Ochsenreither
wrote:
> Sorry, I completely disagree. Imho it is dozen times worse to have two
> methods where of them is just not working, because it can only compare the
> value, but not the types. An alternative would be to implement equals by
> always throwing an exception. But then I would just prefer making a known
> wrong equals comparison a compile time error instead.

That's why libraries such as Scalaz have a different equality
comparison. If you do this, then you are basically breaking both your
equals methods and Scala's equals method, so that we end with NO
equals method. Except, of course, for Scala.

I'm all for fixing equality, but either it is done for everything, or
it is done for nothing. I can compromise on it remaining broken, but
not on having two different versions with the same name.

milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Sat, Feb 4, 2012 at 10:59 AM, Geoff Reedy wrote:
> Good point. I bet you could do something clever with Miles' unboxed tagged types so that Quantity takes implicit Int @ M, Int @ KG, etc. and then there's only the overhead of 7 int fields and maybe no object creation during the implicit resolution.

I'm afraid that's not going to work very well here, because Int @@ M
<: Int, so the compiler wouldn't prevent you from adding dimensioned
and dimensionless quantities, which is pretty much defeating the
object of the exercise.

There's another trick I discovered recently, which is a little closer
to newtype than tagging,

https://gist.github.com/5a76bb0c7a51bea3fabe

but unfortunately the types involved here (eg., Any @@
QuantityTag[Double, M, ...]) will always be boxed.

But I'm not sure this is all that big a deal anyway ... Simon's
quantities are already boxed, so we've paid that price already.

Cheers,

Miles

geoff
Joined: 2008-08-20,
User offline. Last seen 1 year 25 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Feb 4, 2012, at 1:39 PM, Miles Sabin wrote:
> I'm afraid that's not going to work very well here, because Int @@ M
> <: Int, so the compiler wouldn't prevent you from adding dimensioned
> and dimensionless quantities, which is pretty much defeating the
> object of the exercise.

Right. I mean to use the tags to determine the right Int instance to reify the type level integers in the type constructor to the corresponding runtime values. The tags instead of the TypeValue wrappers already present in metascala is to cut down on the allocation done when computing with dimensioned quantities.

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: Units of Measurement — Scala Macros to the rescue?

Gentlemen,

JavaScript has already proved that our == is fine.  We just need the more awesomer === for typesafe equality.

- Josh

On Feb 4, 2012 3:39 PM, "Miles Sabin" <miles@milessabin.com> wrote:
On Sat, Feb 4, 2012 at 10:59 AM, Geoff Reedy <geoff@programmer-monk.net> wrote:
> Good point. I bet you could do something clever with Miles' unboxed tagged types so that Quantity takes implicit Int @ M, Int @ KG, etc. and then there's only the overhead of 7 int fields and maybe no object creation during the implicit resolution.

I'm afraid that's not going to work very well here, because Int @@ M
<: Int, so the compiler wouldn't prevent you from adding dimensioned
and dimensionless quantities, which is pretty much defeating the
object of the exercise.

There's another trick I discovered recently, which is a little closer
to newtype than tagging,

 https://gist.github.com/5a76bb0c7a51bea3fabe

but unfortunately the types involved here (eg., Any @@
QuantityTag[Double, M, ...]) will always be boxed.

But I'm not sure this is all that big a deal anyway ... Simon's
quantities are already boxed, so we've paid that price already.

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
gtalk: miles@milessabin.com
skype: milessabin
g+: http://www.milessabin.com
http://twitter.com/milessabin
http://www.chuusai.com/
Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
So what should happen in my case? I think I prefer a compiler telling an user that he is definitely wrong to an implementation which always throws an exception at runtime.
d_m
Joined: 2010-11-11,
User offline. Last seen 35 weeks 2 days ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Sun, Feb 05, 2012 at 07:53:55AM -0500, Josh Suereth wrote:
> JavaScript has already proved that our == is fine. We just need the more
> awesomer === for typesafe equality.

I like this solution, and it's something some of us are already doing.

Would it be implemented as a type class? In my work, I have a
specialized Eq type class with EqOps providing === and !==. I know
Scalaz also has this operator, although I imagine their implementation
is a bit different (and not specialized).

If Scala were to add === I think it'd be really important to make sure
it was as a specialized type class. Otherwise it will block independent
implementations that are more flexible/fast.

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?

Imho correct solution is to fix == and !=, it will most likely not be backwards compatible, but it fixes a real problem.

eq and ne should be a type of Equivalence (ref equality)

Universal equality is a failed experiment.

On Feb 5, 2012 4:59 PM, "Erik Osheim" <erik@plastic-idolatry.com> wrote:
On Sun, Feb 05, 2012 at 07:53:55AM -0500, Josh Suereth wrote:
> JavaScript has already proved that our == is fine.  We just need the more
> awesomer === for typesafe equality.

I like this solution, and it's something some of us are already doing.

Would it be implemented as a type class? In my work, I have a
specialized Eq type class with EqOps providing === and !==. I know
Scalaz also has this operator, although I imagine their implementation
is a bit different (and not specialized).

If Scala were to add === I think it'd be really important to make sure
it was as a specialized type class. Otherwise it will block independent
implementations that are more flexible/fast.

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Sun, Feb 5, 2012 at 13:55, Simon Ochsenreither
wrote:
> So what should happen in my case? I think I prefer a compiler telling an
> user that he is definitely wrong to an implementation which always throws an
> exception at runtime.

It should just return false. Listen, maybe I did not understand what
the issue here is. The semantics of == is that it compares to objects
of any kind, and the objects decide whether they are equal or not. It
doesn't fail to compile, and it doesn't throw exceptions -- not even
for null. Whether objects of different types are equal or not is up to
them -- Vector(1, 2, 3) == List(1, 2, 3) and 1 == 1.0 are both true,
for example.

So, why is it that you can't abide by this semantic? I do think this
semantics is not a good one and it would be preferable to change it,
but as long as this _is_ the semantics, things should respect it.

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
On Sun, Feb 5, 2012 at 11:04 AM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

Imho correct solution is to fix == and !=, it will most likely not be backwards compatible, but it fixes a real problem.

eq and ne should be a type of Equivalence (ref equality)

Universal equality is a failed experiment.

What equality is _not_ a failed experiment?  For example,

  // Universal equals
  Some(5) == Option(5)   // Compiles, returns true
  Option(5) == Some(5)   // Compiles, returns true

  // Scalaz equals
  Option(5) === Some(5)  // Compiles, returns true
  Some(5) === Option(5)  // DOES NOT COMPILE

What the heck?  Equals isn't a symmetric function now?!

This is as broken as anything in the current implementation with universal equals.

Also, note that Scalaz === has all the same problems as universal equals if you just cast both sides to Any.

First let's _find_ a fix.  Then we can talk about implementing it.  I'm not yet convinced a practical fix exists.

  --Rex

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?


On Sun, Feb 5, 2012 at 5:57 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 11:04 AM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

Imho correct solution is to fix == and !=, it will most likely not be backwards compatible, but it fixes a real problem.

eq and ne should be a type of Equivalence (ref equality)

Universal equality is a failed experiment.

What equality is _not_ a failed experiment?  For example,

  // Universal equals
  Some(5) == Option(5)   // Compiles, returns true
  Option(5) == Some(5)   // Compiles, returns true

  // Scalaz equals
  Option(5) === Some(5)  // Compiles, returns true
  Some(5) === Option(5)  // DOES NOT COMPILE

What the heck?  Equals isn't a symmetric function now?!

You did not say how you wanted to compare them, so no context. 

This is as broken as anything in the current implementation with universal equals.

Also, note that Scalaz === has all the same problems as universal equals if you just cast both sides to Any.

First let's _find_ a fix.  Then we can talk about implementing it.  I'm not yet convinced a practical fix exists.

  --Rex




--
Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang
ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
On Sun, Feb 5, 2012 at 12:09 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 5:57 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 11:04 AM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

Imho correct solution is to fix == and !=, it will most likely not be backwards compatible, but it fixes a real problem.

eq and ne should be a type of Equivalence (ref equality)

Universal equality is a failed experiment.

What equality is _not_ a failed experiment?  For example,

  // Universal equals
  Some(5) == Option(5)   // Compiles, returns true
  Option(5) == Some(5)   // Compiles, returns true

  // Scalaz equals
  Option(5) === Some(5)  // Compiles, returns true
  Some(5) === Option(5)  // DOES NOT COMPILE

What the heck?  Equals isn't a symmetric function now?!

You did not say how you wanted to compare them, so no context.

I gave plenty of context.  I said I wanted equality, which obviously means I'm after some sort of equivalence relation.  Equivalence relations are reflexive, symmetric, and transitive.

=== isn't symmetric--it's enforced to be asymmetric at compile time!

So === is not an equivalence relation.

If that isn't a failure for something called "equality" (or implemented via the trait Equals), I don't know what is.

At least with universal == you can rescue these things if you must via

  (a==b && b==a)

to allow either side to object and thereby restore symmetry.  You can't even do that with scalaz === without knowing what the types are, because even though the underlying data might be identical, you might have different type ascriptions.

I'm not bashing Scalaz here--this is a tough problem for an object-oriented language, and it's better to have broken == and broken === than only one, so you can choose the less broken method for your use case.

Substituting one broken behavior for another isn't the kind of progress I'd like to see, however.

  --Rex

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?


On Sun, Feb 5, 2012 at 6:26 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 12:09 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 5:57 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 11:04 AM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

Imho correct solution is to fix == and !=, it will most likely not be backwards compatible, but it fixes a real problem.

eq and ne should be a type of Equivalence (ref equality)

Universal equality is a failed experiment.

What equality is _not_ a failed experiment?  For example,

  // Universal equals
  Some(5) == Option(5)   // Compiles, returns true
  Option(5) == Some(5)   // Compiles, returns true

  // Scalaz equals
  Option(5) === Some(5)  // Compiles, returns true
  Some(5) === Option(5)  // DOES NOT COMPILE

What the heck?  Equals isn't a symmetric function now?!

You did not say how you wanted to compare them, so no context.

I gave plenty of context.  I said I wanted equality, which obviously means I'm after some sort of equivalence relation.

Excatly, you didn't say how you wanted to test them for equality. 
  Equivalence relations are reflexive, symmetric, and transitive.

=== isn't symmetric--it's enforced to be asymmetric at compile time!

What I'm saying that you should be forced to specify _how_ they are to be considered equal, in this context.  

So === is not an equivalence relation.

I wasn't arguing that. === definitely seems broken, I'm surprised that the first example compiled. 

If that isn't a failure for something called "equality" (or implemented via the trait Equals), I don't know what is.

At least with universal == you can rescue these things if you must via

I'd love to see a run-through of all implementations of .equals on the JVM, I'd be surprised if the majority are correctly implemented (according to the contract specified in the spec for the method).  

  (a==b && b==a)

to allow either side to object and thereby restore symmetry.  You can't even do that with scalaz === without knowing what the types are, because even though the underlying data might be identical, you might have different type ascriptions.

I'm not bashing Scalaz here--this is a tough problem for an object-oriented language, and it's better to have broken == and broken === than only one, so you can choose the less broken method for your use case.

Substituting one broken behavior for another isn't the kind of progress I'd like to see, however.

Exactly my point. You should have to specify the context.  


  --Rex




--
Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang
milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Sun, Feb 5, 2012 at 5:32 PM, √iktor Ҡlang wrote:
> On Sun, Feb 5, 2012 at 6:26 PM, Rex Kerr wrote:
>> I gave plenty of context.  I said I wanted equality, which obviously means
>> I'm after some sort of equivalence relation.
>
> Excatly, you didn't say how you wanted to test them for equality.

What Rex is saying (quite reasonably IMO) is that whatever the X in
"equality wrt to X" it should at least be an equivalence relation, ie.
reflexive, symmetric and transitive.

Cheers,

Miles

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Sun, Feb 5, 2012 at 12:32 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 6:26 PM, Rex Kerr <ichoran@gmail.com> wrote:
I gave plenty of context.  I said I wanted equality, which obviously means I'm after some sort of equivalence relation.

Excatly, you didn't say how you wanted to test them for equality.

How would one do that so that it isn't an enormous pain in the neck?
 
 
  Equivalence relations are reflexive, symmetric, and transitive.

=== isn't symmetric--it's enforced to be asymmetric at compile time!

What I'm saying that you should be forced to specify _how_ they are to be considered equal, in this context.

Generally, if the class is the same and the values in the class are the same, people want to call them the same.  Shouldn't be terribly controversial.
 
 

So === is not an equivalence relation.

I wasn't arguing that. === definitely seems broken, I'm surprised that the first example compiled.

But it has to, or it violates LSP.

Substituting one broken behavior for another isn't the kind of progress I'd like to see, however.

Exactly my point. You should have to specify the context.

I don't see how that helps.

  --Rex

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?


On Sun, Feb 5, 2012 at 6:58 PM, Rex Kerr <ichoran@gmail.com> wrote:

On Sun, Feb 5, 2012 at 12:32 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 6:26 PM, Rex Kerr <ichoran@gmail.com> wrote:
I gave plenty of context.  I said I wanted equality, which obviously means I'm after some sort of equivalence relation.

Excatly, you didn't say how you wanted to test them for equality.

How would one do that so that it isn't an enormous pain in the neck?
 
 
  Equivalence relations are reflexive, symmetric, and transitive.

=== isn't symmetric--it's enforced to be asymmetric at compile time!

What I'm saying that you should be forced to specify _how_ they are to be considered equal, in this context.

Generally, if the class is the same and the values in the class are the same, people want to call them the same.  Shouldn't be terribly controversial.
 
 

So === is not an equivalence relation.

I wasn't arguing that. === definitely seems broken, I'm surprised that the first example compiled.

But it has to, or it violates LSP.

if neither x === y nor y === x compiles, how does that violate LSP? 

Substituting one broken behavior for another isn't the kind of progress I'd like to see, however.

Exactly my point. You should have to specify the context.

I don't see how that helps.

For example:
scala> def f = 0f: Int
scala> val x = f _ x: () => Int = <function0>
scala> val y = f _y: () => Int = <function0>
scala> x == yres0: Boolean = false
scala> y == xres1: Boolean = false

Do we agree that there could exist such a context where x would be equal to y? 


  --Rex




--
Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang
ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
On Sun, Feb 5, 2012 at 1:05 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 6:58 PM, Rex Kerr <ichoran@gmail.com> wrote:

On Sun, Feb 5, 2012 at 12:32 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 6:26 PM, Rex Kerr <ichoran@gmail.com> wrote:
I gave plenty of context.  I said I wanted equality, which obviously means I'm after some sort of equivalence relation.

Excatly, you didn't say how you wanted to test them for equality.

How would one do that so that it isn't an enormous pain in the neck?
 
 
  Equivalence relations are reflexive, symmetric, and transitive.

=== isn't symmetric--it's enforced to be asymmetric at compile time!

What I'm saying that you should be forced to specify _how_ they are to be considered equal, in this context.

Generally, if the class is the same and the values in the class are the same, people want to call them the same.  Shouldn't be terribly controversial.
 
 

So === is not an equivalence relation.

I wasn't arguing that. === definitely seems broken, I'm surprised that the first example compiled.

But it has to, or it violates LSP.

if neither x === y nor y === x compiles, how does that violate LSP?

Let x1 have the same type as x, and let y be typed as a subclass of the type of x.

By LSP, we should be able to insert y anywhere we see x1.

  x === x1

compiles or not?

If no, this violates reflexivity of equivalence relations.
 
 

Substituting one broken behavior for another isn't the kind of progress I'd like to see, however.

Exactly my point. You should have to specify the context.

I don't see how that helps.

For example:
scala> def f = 0f: Int
scala> val x = f _ x: () => Int = <function0>
scala> val y = f _y: () => Int = <function0>
scala> x == yres0: Boolean = false
scala> y == xres1: Boolean = false
Do we agree that there could exist such a context where x would be equal to y?

Sure, but this is an entirely different problem.  I don't see how that helps the difficult problems of equals.

You're always free to choose some other binary relation to use in special cases.  That doesn't mean that it's unhelpful to provide a sensible default.  (Which I would argue is one where x and y are equal, unlike the current implementation, but that's yet again another matter.)

  --Rex

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?


On Sun, Feb 5, 2012 at 7:13 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:05 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 6:58 PM, Rex Kerr <ichoran@gmail.com> wrote:

On Sun, Feb 5, 2012 at 12:32 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 6:26 PM, Rex Kerr <ichoran@gmail.com> wrote:
I gave plenty of context.  I said I wanted equality, which obviously means I'm after some sort of equivalence relation.

Excatly, you didn't say how you wanted to test them for equality.

How would one do that so that it isn't an enormous pain in the neck?
 
 
  Equivalence relations are reflexive, symmetric, and transitive.

=== isn't symmetric--it's enforced to be asymmetric at compile time!

What I'm saying that you should be forced to specify _how_ they are to be considered equal, in this context.

Generally, if the class is the same and the values in the class are the same, people want to call them the same.  Shouldn't be terribly controversial.
 
 

So === is not an equivalence relation.

I wasn't arguing that. === definitely seems broken, I'm surprised that the first example compiled.

But it has to, or it violates LSP.

if neither x === y nor y === x compiles, how does that violate LSP?

Let x1 have the same type as x, and let y be typed as a subclass of the type of x.

By LSP, we should be able to insert y anywhere we see x1.

  x === x1

compiles or not?

If no, this violates reflexivity of equivalence relations.

You're assuming some implementation of === I'm not. What I'm saying is that there should be a context that does the equality.  
 
 

Substituting one broken behavior for another isn't the kind of progress I'd like to see, however.

Exactly my point. You should have to specify the context.

I don't see how that helps.

For example:
scala> def f = 0f: Int
scala> val x = f _ x: () => Int = <function0>
scala> val y = f _y: () => Int = <function0>
scala> x == yres0: Boolean = false
scala> y == xres1: Boolean = false
Do we agree that there could exist such a context where x would be equal to y?

Sure, but this is an entirely different problem.  I don't see how that helps the difficult problems of equals.

You're always free to choose some other binary relation to use in special cases.  That doesn't mean that it's unhelpful to provide a sensible default. 

Then I'd probably argue that structural equality should be the default.  
(Which I would argue is one where x and y are equal, unlike the current implementation, but that's yet again another matter.)

Where the structure of a function hopefully would satisfy your requirement.
Cheers,√ 


  --Rex




--
Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang
geoff
Joined: 2008-08-20,
User offline. Last seen 1 year 25 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Feb 5, 2012, at 10:45 AM, Miles Sabin wrote:
> What Rex is saying (quite reasonably IMO) is that whatever the X in
> "equality wrt to X" it should at least be an equivalence relation, ie.
> reflexive, symmetric and transitive.

Shouldn't === use the equivalence relation for the LUB of the argument types.

Given

a: A
b: B
C <: A
C <: B
D <: C

with

eqD being the equivalence relation wrt D
eqC being the equivalence relation wrt C

then you should have

eqD ⊆ eqC

which gives

eqD(a,b) => eqC(a,b)

all by the substitutability principle.

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
On Sun, Feb 5, 2012 at 1:18 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 7:13 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:05 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

if neither x === y nor y === x compiles, how does that violate LSP?

Let x1 have the same type as x, and let y be typed as a subclass of the type of x.

By LSP, we should be able to insert y anywhere we see x1.

  x === x1

compiles or not?

If no, this violates reflexivity of equivalence relations.

You're assuming some implementation of === I'm not. What I'm saying is that there should be a context that does the equality.

I'm assuming that === implements _any_ sort of equivalence relation.  Any conceivable equivalence relation at all.  I don't care which one.  All it must be is an equivalence relation.

Now for any method at all, LSP tells us that if
  A <: B
  a: A
  b: B
then if
  f(b)
compiles
  f(a)
must also compile.

Let's move from a method f to a relation r.  If we have
  a: A
  b0: B
  b1: B
then if
  r(b0, b1)
compiles, so must
  r(a, b1)
  r(b0, a)
  r(a, a)

Okay?

Now, let's say that r is an equivalence relation.  Therefore, for any x and y,
  r(x,x) is true
  r(y,x) returns the same value as r(x,y)
  r(x,y) and r(y,z) imply r(x,z)

I don't understand why you keep mentioning implementations.  This is all entirely implementation-agnostic.  It's the bare minimum properties you must obey in order to be called an equivalence relation and a subclass.

  b === b    // Must compile and return true by reflexivity
  b === a    // Must compile by LSP
  a === b    // Must compile and return the same answer by symmetry

  --Rex

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?


On Sun, Feb 5, 2012 at 7:30 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:18 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 7:13 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:05 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

if neither x === y nor y === x compiles, how does that violate LSP?

Let x1 have the same type as x, and let y be typed as a subclass of the type of x.

By LSP, we should be able to insert y anywhere we see x1.

  x === x1

compiles or not?

If no, this violates reflexivity of equivalence relations.

You're assuming some implementation of === I'm not. What I'm saying is that there should be a context that does the equality.

I'm assuming that === implements _any_ sort of equivalence relation.  Any conceivable equivalence relation at all.  I don't care which one.  All it must be is an equivalence relation.

My point was that I thought === was broken, as is. And I think it's weird that equality doesn't require context. 

Now for any method at all, LSP tells us that if
  A <: B
  a: A
  b: B
then if
  f(b)
compiles
  f(a)
must also compile.

Let's move from a method f to a relation r.  If we have
  a: A
  b0: B
  b1: B
then if
  r(b0, b1)
compiles, so must
  r(a, b1)
  r(b0, a)
  r(a, a)

Okay?

Now, let's say that r is an equivalence relation.  Therefore, for any x and y,
  r(x,x) is true
  r(y,x) returns the same value as r(x,y)
  r(x,y) and r(y,z) imply r(x,z)

I don't understand why you keep mentioning implementations.  This is all entirely implementation-agnostic.  It's the bare minimum properties you must obey in order to be called an equivalence relation and a subclass.

  b === b    // Must compile and return true by reflexivity
  b === a    // Must compile by LSP
  a === b    // Must compile and return the same answer by symmetry

  --Rex




--
Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang
DaveScala
Joined: 2011-03-18,
User offline. Last seen 1 year 21 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?

The scalaz version can be made symmetric if === is implemented as a
compile time macro which checks its symmetric counterpart.

So if the source code says:
5L === 5

its doing
5L === 5 // returns true
and
5 === 5L // type mismatch
and the result is type mismatch

and if the source code says:
5 === 5L

5 === 5L // type mismatch
and (the latter doesn't have to be tested )
5L === 5 // returns true
and the result is type mismatch

On 5 feb, 18:45, Miles Sabin wrote:
> On Sun, Feb 5, 2012 at 5:32 PM, √iktor Ҡlang wrote:
> > On Sun, Feb 5, 2012 at 6:26 PM, Rex Kerr wrote:
> >> I gave plenty of context.  I said I wanted equality, which obviously means
> >> I'm after some sort of equivalence relation.
>
> > Excatly, you didn't say how you wanted to test them for equality.
>
> What Rex is saying (quite reasonably IMO) is that whatever the X in
> "equality wrt to X" it should at least be an equivalence relation, ie.
> reflexive, symmetric and transitive.
>
> Cheers,
>
> Miles
>
> --
> Miles Sabin
> tel: +44 7813 944 528
> gtalk: mi...@milessabin.com
> skype: milessabin
> g+:http://www.milessabin.comhttp://twitter.com/milessabinhttp://www.chuusai.com/

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
On Sun, Feb 5, 2012 at 1:39 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

On Sun, Feb 5, 2012 at 7:30 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:18 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 7:13 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:05 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

if neither x === y nor y === x compiles, how does that violate LSP?

Let x1 have the same type as x, and let y be typed as a subclass of the type of x.

By LSP, we should be able to insert y anywhere we see x1.

  x === x1

compiles or not?

If no, this violates reflexivity of equivalence relations.

You're assuming some implementation of === I'm not. What I'm saying is that there should be a context that does the equality.

I'm assuming that === implements _any_ sort of equivalence relation.  Any conceivable equivalence relation at all.  I don't care which one.  All it must be is an equivalence relation.

My point was that I thought === was broken, as is. And I think it's weird that equality doesn't require context. 

Fine, but you advocated a revamp of equality.  Do you know of a way to do it, with or without context, that isn't broken, and isn't an enormous burden for simple cases?

If the answer is "yes", I'd like to know what it is.

If the answer is "no", while I agree that it would be lovely to have that type of equality, talking about replacing what we've got is premature when we don't know what would work instead.

  --Rex

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: Units of Measurement — Scala Macros to the rescue?

Indeed. It could check if one side is a subtype of the other, and
always call equals on the least specific, or fail to compile.

On Sun, Feb 5, 2012 at 16:34, Dave wrote:
> The scalaz version can be made symmetric if === is implemented as a
> compile time macro which checks its symmetric counterpart.
>
> So if the source code says:
> 5L === 5
>
> its doing
> 5L === 5  // returns true
> and
> 5 === 5L  // type mismatch
> and the result is type mismatch
>
> and if the source code says:
> 5 === 5L
>
> 5 === 5L  // type mismatch
> and (the latter doesn't have to be tested )
> 5L === 5  // returns true
> and the result is type mismatch
>
>
> On 5 feb, 18:45, Miles Sabin wrote:
>> On Sun, Feb 5, 2012 at 5:32 PM, √iktor Ҡlang wrote:
>> > On Sun, Feb 5, 2012 at 6:26 PM, Rex Kerr wrote:
>> >> I gave plenty of context.  I said I wanted equality, which obviously means
>> >> I'm after some sort of equivalence relation.
>>
>> > Excatly, you didn't say how you wanted to test them for equality.
>>
>> What Rex is saying (quite reasonably IMO) is that whatever the X in
>> "equality wrt to X" it should at least be an equivalence relation, ie.
>> reflexive, symmetric and transitive.
>>
>> Cheers,
>>
>> Miles
>>
>> --
>> Miles Sabin
>> tel: +44 7813 944 528
>> gtalk: mi...@milessabin.com
>> skype: milessabin
>> g+:http://www.milessabin.comhttp://twitter.com/milessabinhttp://www.chuusai.com/

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?


On Sun, Feb 5, 2012 at 7:48 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:39 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

On Sun, Feb 5, 2012 at 7:30 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:18 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 7:13 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:05 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

if neither x === y nor y === x compiles, how does that violate LSP?

Let x1 have the same type as x, and let y be typed as a subclass of the type of x.

By LSP, we should be able to insert y anywhere we see x1.

  x === x1

compiles or not?

If no, this violates reflexivity of equivalence relations.

You're assuming some implementation of === I'm not. What I'm saying is that there should be a context that does the equality.

I'm assuming that === implements _any_ sort of equivalence relation.  Any conceivable equivalence relation at all.  I don't care which one.  All it must be is an equivalence relation.

My point was that I thought === was broken, as is. And I think it's weird that equality doesn't require context. 

Fine, but you advocated a revamp of equality.  Do you know of a way to do it, with or without context, that isn't broken, and isn't an enormous burden for simple cases?

If the answer is "yes", I'd like to know what it is.

I don't have a pull request with a bytecode rewriter to offer no. 

If the answer is "no", while I agree that it would be lovely to have that type of equality, talking about replacing what we've got is premature when we don't know what would work instead.

Well, that's why I'm discussing an admittedtly not backwards compatible solution. 


  --Rex




--
Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang
ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
On Sun, Feb 5, 2012 at 1:51 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 7:48 PM, Rex Kerr <ichoran@gmail.com> wrote:

Fine, but you advocated a revamp of equality.  Do you know of a way to do it, with or without context, that isn't broken, and isn't an enormous burden for simple cases?

If the answer is "yes", I'd like to know what it is.

I don't have a pull request with a bytecode rewriter to offer no.

Do you have a conceptual solution?  I can't tell yet whether you have one but aren't explaining it clearly, or you don't have one and know you don't (but think that context is part of the solution), or you think you have one but missed one of the key requirements.

No point wasting any more time thinking about a difficult problem if it's already been conceptually solved, except to get to work on coding it.

  --Rex

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?

You need a + b and a (A,B) => Boolean

The latter is the context in which they are either equal or not.

Sprinkle sugar/macros to get it syntactically pleasant and call it a day.

It will require more work yes, but things won't be as surprising.

On Feb 5, 2012 8:01 PM, "Rex Kerr" <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:51 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 7:48 PM, Rex Kerr <ichoran@gmail.com> wrote:

Fine, but you advocated a revamp of equality.  Do you know of a way to do it, with or without context, that isn't broken, and isn't an enormous burden for simple cases?

If the answer is "yes", I'd like to know what it is.

I don't have a pull request with a bytecode rewriter to offer no.

Do you have a conceptual solution?  I can't tell yet whether you have one but aren't explaining it clearly, or you don't have one and know you don't (but think that context is part of the solution), or you think you have one but missed one of the key requirements.

No point wasting any more time thinking about a difficult problem if it's already been conceptually solved, except to get to work on coding it.

  --Rex

roland.kuhn
Joined: 2011-02-21,
User offline. Last seen 35 weeks 3 days ago.
Re: Units of Measurement — Scala Macros to the rescue?
And then you add “implicit val eq = (a: Any, b: Any) => a.equals(b)” to fix that long-standing Scala bug that “a == b” does not throw NPE when “a eq null” ;-) (sorry, couldn’t resist)

Am Sonntag, 5. Februar 2012 20:13:29 UTC+1 schrieb √iktor Klang:

You need a + b and a (A,B) => Boolean

The latter is the context in which they are either equal or not.

Sprinkle sugar/macros to get it syntactically pleasant and call it a day.

It will require more work yes, but things won't be as surprising.

On Feb 5, 2012 8:01 PM, "Rex Kerr" <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 1:51 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:


On Sun, Feb 5, 2012 at 7:48 PM, Rex Kerr <ichoran@gmail.com> wrote:

Fine, but you advocated a revamp of equality.  Do you know of a way to do it, with or without context, that isn't broken, and isn't an enormous burden for simple cases?

If the answer is "yes", I'd like to know what it is.

I don't have a pull request with a bytecode rewriter to offer no.

Do you have a conceptual solution?  I can't tell yet whether you have one but aren't explaining it clearly, or you don't have one and know you don't (but think that context is part of the solution), or you think you have one but missed one of the key requirements.

No point wasting any more time thinking about a difficult problem if it's already been conceptually solved, except to get to work on coding it.

  --Rex

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Units of Measurement — Scala Macros to the rescue?
On Sun, Feb 5, 2012 at 5:57 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 11:04 AM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

Imho correct solution is to fix == and !=, it will most likely not be backwards compatible, but it fixes a real problem.

eq and ne should be a type of Equivalence (ref equality)

Universal equality is a failed experiment.

What equality is _not_ a failed experiment?  For example,

  // Universal equals
  Some(5) == Option(5)   // Compiles, returns true
  Option(5) == Some(5)   // Compiles, returns true

  // Scalaz equals
  Option(5) === Some(5)  // Compiles, returns true
  Some(5) === Option(5)  // DOES NOT COMPILE

What the heck?  Equals isn't a symmetric function now?!

This is as broken as anything in the current implementation with universal equals.

Also, note that Scalaz === has all the same problems as universal equals if you just cast both sides to Any.

First let's _find_ a fix.  Then we can talk about implementing it.  I'm not yet convinced a practical fix exists.

Another approach is to avoid inferring the type when using type-class based equality.
  Equal[A].equal(a1, a2)
This is symmetric.
Ugly, sure, but it lets us separately the discussion of the Equal type class from its corresponding "syntax" (our term for the implicitly added methods, like ===, enabled by a type class.)
You could use this for a slightly safer version of Any#==.
  def equal[A](a1: A, a2: A) = a1 == a2  equal[Int](0, 1)
-jason
ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
On Sun, Feb 5, 2012 at 2:13 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

You need a + b and a (A,B) => Boolean

The latter is the context in which they are either equal or not.

Sprinkle sugar/macros to get it syntactically pleasant and call it a day.

It will require more work yes, but things won't be as surprising.

Okay, so your proposal is to take the idea of equivalence away from individual classes and instead have a parallel set of binary relations that encapsulate equivalence.  This solves the problem of typed equivalence (assuming it can be made to be non-headachy enough), and you can declare that the only equivalence that is solved is typed equivalence.  Instance equivalence is full of dragons anyway.

In order for this to be a solution that yields an equivalence relation, for any B
  r: (B,B) => Boolean
must exist, and if A <: B then either both or neither of the pair
  r1: (A,B) => Boolean
  r2: (B,A) => Boolean
must exist and if they do then for all a,b
  r1(a,b) if and only if r2(b,a)
which suggests that you should only be allowed to create one (e.g. (A,B)) and then
  b === a
would actually call r1(a,b).

Furthermore, in order to be meaningful, the most specific version available must get called.  And in order to provide Java interoperability, one would want to construct
  implicit def defaultEquiv[A](a: A): (A,A)=>Boolean = (a1,a2) => a1.equals(a2)
(via some scheme whereby it only would have to happen once, not once per usage, unless one wants some pretty hefty overhead, and where the A-version, not whatever subclassed version a1 actually had, was used).  But one would want the standard LUB mechanism to _not_ always drift all the way up to (Any,Any), but rather give a compiler error if neither side was a subclass of the other.

The problem with this approach, of course, is that type erasure ruins the entire scheme, so to even get simple equality, you have to pass in these equivalences from wherever you actually have the type information.  Not an insurmountable problem, but it does require a lot of work.

Another problem is that certain hierarchies would have incomparable leaf-nodes, but I guess the idea is that you'd either use traditional == for those, or you'd fill in the requisite equivalence relations.

So...hm...not sure if this is workable or not, but it _might_ be.  Time to SIP?  Looks to me like this would require significant additional help from the compiler.

  --Rex

andrevandelft
Joined: 2010-02-07,
User offline. Last seen 34 weeks 1 day ago.
Re: Units of Measurement — Scala Macros to the rescue?

Simon,

I saw your example code at https://github.com/soc/scalax-units
Nice work, but i have some remarks.

I find the restriction to 7 SI units too limited.

Moreover, by writing "5 s" we essentially mean "5*s"; we just left
out
the multiplication operator as we often do with mathematical
expressions.
I do not think this shorthand notation should be supported in
programming
languages; at least not just for supporting the usual notation for
dimensioned numbers.

A unit is a physical quantity, and any physical quantity can serve as
a unit.
As soon as we start multiplying with units, divisions start to make
more sense, as in
"speed = 9*m/s".

Is a toString method really needed on dimensioned numbers?
Can't we just forbid expressions that would invoke it?
Back in 1999 I published a paper on a Java extension for supporting
physical
dimensions and units of measurement, in Software, Practice and
Experience.
You may download it from
http://code.google.com/p/subscript/downloads/detail?name=A%20Java%20exte...

I simply forbade conversion to strings from dimensioned numbers. I
wrote the following:

(start of quote)

The Java string concatenation operator ‘+’ automatically converts
numbers into strings. These numbers must have empty dimension.
So the following would be illegal:

double * Time t = 18.3*second;
double * Length s = 64.2*meter;
System.out.println (“speed: “ + (s/t)); // compile error

We first need to “divide off” the dimension present in the expression
s/t.
This can be done by dividing it by a unit of equal dimension, for
instance kilometer/hour;
the result then represents the number of kilometers per hour:

System.out.println (“speed: “+ ((s/t) / (1.0*kilometer/hour)) + “ km/
h”);

(end of quote)

I don't know what I like more: my old "double*Time" notation, or your
"Time[Double]".
Did you consider "Double[Time]"?

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?


On Sun, Feb 5, 2012 at 8:58 PM, Rex Kerr <ichoran@gmail.com> wrote:
On Sun, Feb 5, 2012 at 2:13 PM, √iktor Ҡlang <viktor.klang@gmail.com> wrote:

You need a + b and a (A,B) => Boolean

The latter is the context in which they are either equal or not.

Sprinkle sugar/macros to get it syntactically pleasant and call it a day.

It will require more work yes, but things won't be as surprising.

Okay, so your proposal is to take the idea of equivalence away from individual classes and instead have a parallel set of binary relations that encapsulate equivalence.  This solves the problem of typed equivalence (assuming it can be made to be non-headachy enough), and you can declare that the only equivalence that is solved is typed equivalence.  Instance equivalence is full of dragons anyway.

In order for this to be a solution that yields an equivalence relation, for any B
  r: (B,B) => Boolean
must exist, and if A <: B then either both or neither of the pair
  r1: (A,B) => Boolean
  r2: (B,A) => Boolean
must exist and if they do then for all a,b
  r1(a,b) if and only if r2(b,a)
which suggests that you should only be allowed to create one (e.g. (A,B)) and then
  b === a
would actually call r1(a,b).

Furthermore, in order to be meaningful, the most specific version available must get called.  And in order to provide Java interoperability, one would want to construct
  implicit def defaultEquiv[A](a: A): (A,A)=>Boolean = (a1,a2) => a1.equals(a2)
(via some scheme whereby it only would have to happen once, not once per usage, unless one wants some pretty hefty overhead, and where the A-version, not whatever subclassed version a1 actually had, was used).  But one would want the standard LUB mechanism to _not_ always drift all the way up to (Any,Any), but rather give a compiler error if neither side was a subclass of the other.

The problem with this approach, of course, is that type erasure ruins the entire scheme, so to even get simple equality, you have to pass in these equivalences from wherever you actually have the type information.  Not an insurmountable problem, but it does require a lot of work.

Another problem is that certain hierarchies would have incomparable leaf-nodes, but I guess the idea is that you'd either use traditional == for those, or you'd fill in the requisite equivalence relations.

So...hm...not sure if this is workable or not, but it _might_ be.  Time to SIP?  Looks to me like this would require significant additional help from the compiler.

Yeah, I was talking to Martin about this last thursday. When I've got Akka 2.0 out the door and SIP14 is done I might get some time to take a stab at this.
Cheers,√ 


  --Rex




--
Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang
Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
I think putting almost religious rules above user experience is a wide-spread disease in Java and I prefer not to replicate it.
I think I don't violate any semantics. The semantics apply to runtime, not compile time.

If a meaningful implementation of a method cannot provided because 7 of the 8 pieces of information to do it are missing (at runtime) I clearly prefer to tell people upfront, instead of watching them fail.
Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
Hi Andre,

thanks for your constructive comment, I really appreciate it.

I have thought about supporting more units, but have postponed that decision until everything else works.
The question really is if I want to build a "general" system so to speak, where potentially every type is supported. Or something more specialized to scientific purposes while making it possible for other people to just write their own system in which units can be combined with each other.

Which units are in your opinion worth adding?

The bit about "5 s" vs. "5 * s" is not just syntax. I experimented with the second syntax a lot and from my experience supporting the second syntax would make the system behind look quite a bit different. The original implementation does use yet another syntax, but didn't support different numeric types at all (The just had Length, not Length[T]).

My experience is that trying to get the second syntax is much more difficult in terms of typing, type inference and implementation. But maybe I just missed something important, that's completely possible of course. The problem is that "s", "m", ... need to be polymorphic method calls where the type is derived from the math operation, which derives it from the number. (I'm thinking about the "s * 42" case here.) Type inference usually doesn't flow backwards, so this is a real problem...

I'll read your paper, I'm sure it will be very helpful, thanks for linking it!

I'm trying to have a nice, real-world implementation so having a sensible toString and equals are high-priority. Maybe the stuff I'm using is complicated, but I shouldn't punish the user for it.

Thanks Andre!

Bye,

Simon
Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
Hi Andre,

thanks for your constructive comment, I really appreciate it.

I have thought about supporting more units, but have postponed that decision until everything else works.
The question really is if I want to build a "general" system so to speak, where potentially every type is supported. Or something more specialized to scientific purposes while making it possible for other people to just write their own system in which units can be combined with each other.

Which units are in your opinion worth adding?

The bit about "5 s" vs. "5 * s" is not just syntax. I experimented with the second syntax a lot and from my experience supporting the second syntax would make the system behind look quite a bit different. The original implementation does use yet another syntax, but didn't support different numeric types at all (The just had Length, not Length[T]).

My experience is that trying to get the second syntax is much more difficult in terms of typing, type inference and implementation. But maybe I just missed something important, that's completely possible of course. The problem is that "s", "m", ... need to be polymorphic method calls where the type is derived from the math operation, which derives it from the number. (I'm thinking about the "s * 42" case here.) Type inference usually doesn't flow backwards, so this is a real problem...

I'll read your paper, I'm sure it will be very helpful, thanks for linking it!

I'm trying to have a nice, real-world implementation so having a sensible toString and equals are high-priority. Maybe the stuff I'm using is complicated, but I shouldn't punish the user for it.

I'm not sure I understand the remark about double*Time/Time[Double]/Double[Time] ... I'm using pure Scala, no language extension or compiler plugin. This rules out the first one. Also, Double is _the_ standard Scala/Java Double type, which has no type parameters, so I can't add any.

Thanks Andre!

Bye,

Simon

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Units of Measurement — Scala Macros to the rescue?

On Sun, Feb 5, 2012 at 18:47, √iktor Ҡlang wrote:
>
>
> On Sun, Feb 5, 2012 at 8:58 PM, Rex Kerr wrote:
>>
>> On Sun, Feb 5, 2012 at 2:13 PM, √iktor Ҡlang
>> wrote:
>>>
>>> You need a + b and a (A,B) => Boolean
>>>
>>> The latter is the context in which they are either equal or not.
>>>
>>> Sprinkle sugar/macros to get it syntactically pleasant and call it a day.
>>>
>>> It will require more work yes, but things won't be as surprising.
>>
>> Okay, so your proposal is to take the idea of equivalence away from
>> individual classes and instead have a parallel set of binary relations that
>> encapsulate equivalence.  This solves the problem of typed equivalence
>> (assuming it can be made to be non-headachy enough), and you can declare
>> that the only equivalence that is solved is typed equivalence.  Instance
>> equivalence is full of dragons anyway.
>>
>> In order for this to be a solution that yields an equivalence relation,
>> for any B
>>   r: (B,B) => Boolean
>> must exist, and if A <: B then either both or neither of the pair
>>   r1: (A,B) => Boolean
>>   r2: (B,A) => Boolean
>> must exist and if they do then for all a,b
>>   r1(a,b) if and only if r2(b,a)
>> which suggests that you should only be allowed to create one (e.g. (A,B))
>> and then
>>   b === a
>> would actually call r1(a,b).
>>
>> Furthermore, in order to be meaningful, the most specific version
>> available must get called.  And in order to provide Java interoperability,
>> one would want to construct
>>   implicit def defaultEquiv[A](a: A): (A,A)=>Boolean = (a1,a2) =>
>> a1.equals(a2)
>> (via some scheme whereby it only would have to happen once, not once per
>> usage, unless one wants some pretty hefty overhead, and where the A-version,
>> not whatever subclassed version a1 actually had, was used).  But one would
>> want the standard LUB mechanism to _not_ always drift all the way up to
>> (Any,Any), but rather give a compiler error if neither side was a subclass
>> of the other.
>>
>> The problem with this approach, of course, is that type erasure ruins the
>> entire scheme, so to even get simple equality, you have to pass in these
>> equivalences from wherever you actually have the type information.  Not an
>> insurmountable problem, but it does require a lot of work.
>>
>> Another problem is that certain hierarchies would have incomparable
>> leaf-nodes, but I guess the idea is that you'd either use traditional == for
>> those, or you'd fill in the requisite equivalence relations.
>>
>> So...hm...not sure if this is workable or not, but it _might_ be.  Time to
>> SIP?  Looks to me like this would require significant additional help from
>> the compiler.
>
>
> Yeah, I was talking to Martin about this last thursday. When I've got Akka
> 2.0 out the door and SIP14 is done I might get some time to take a stab at
> this.

So, if I translate legend-of-klang time units into SI units, does it
mean it will be done by Friday? :-)

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?


On Sun, Feb 5, 2012 at 11:58 PM, Daniel Sobral <dcsobral@gmail.com> wrote:
On Sun, Feb 5, 2012 at 18:47, √iktor Ҡlang <viktor.klang@gmail.com> wrote:
>
>
> On Sun, Feb 5, 2012 at 8:58 PM, Rex Kerr <ichoran@gmail.com> wrote:
>>
>> On Sun, Feb 5, 2012 at 2:13 PM, √iktor Ҡlang <viktor.klang@gmail.com>
>> wrote:
>>>
>>> You need a + b and a (A,B) => Boolean
>>>
>>> The latter is the context in which they are either equal or not.
>>>
>>> Sprinkle sugar/macros to get it syntactically pleasant and call it a day.
>>>
>>> It will require more work yes, but things won't be as surprising.
>>
>> Okay, so your proposal is to take the idea of equivalence away from
>> individual classes and instead have a parallel set of binary relations that
>> encapsulate equivalence.  This solves the problem of typed equivalence
>> (assuming it can be made to be non-headachy enough), and you can declare
>> that the only equivalence that is solved is typed equivalence.  Instance
>> equivalence is full of dragons anyway.
>>
>> In order for this to be a solution that yields an equivalence relation,
>> for any B
>>   r: (B,B) => Boolean
>> must exist, and if A <: B then either both or neither of the pair
>>   r1: (A,B) => Boolean
>>   r2: (B,A) => Boolean
>> must exist and if they do then for all a,b
>>   r1(a,b) if and only if r2(b,a)
>> which suggests that you should only be allowed to create one (e.g. (A,B))
>> and then
>>   b === a
>> would actually call r1(a,b).
>>
>> Furthermore, in order to be meaningful, the most specific version
>> available must get called.  And in order to provide Java interoperability,
>> one would want to construct
>>   implicit def defaultEquiv[A](a: A): (A,A)=>Boolean = (a1,a2) =>
>> a1.equals(a2)
>> (via some scheme whereby it only would have to happen once, not once per
>> usage, unless one wants some pretty hefty overhead, and where the A-version,
>> not whatever subclassed version a1 actually had, was used).  But one would
>> want the standard LUB mechanism to _not_ always drift all the way up to
>> (Any,Any), but rather give a compiler error if neither side was a subclass
>> of the other.
>>
>> The problem with this approach, of course, is that type erasure ruins the
>> entire scheme, so to even get simple equality, you have to pass in these
>> equivalences from wherever you actually have the type information.  Not an
>> insurmountable problem, but it does require a lot of work.
>>
>> Another problem is that certain hierarchies would have incomparable
>> leaf-nodes, but I guess the idea is that you'd either use traditional == for
>> those, or you'd fill in the requisite equivalence relations.
>>
>> So...hm...not sure if this is workable or not, but it _might_ be.  Time to
>> SIP?  Looks to me like this would require significant additional help from
>> the compiler.
>
>
> Yeah, I was talking to Martin about this last thursday. When I've got Akka
> 2.0 out the door and SIP14 is done I might get some time to take a stab at
> this.

So, if I translate legend-of-klang time units into SI units, does it
mean it will be done by Friday? :-)

I could definitely use some beauty sleep ;-) 

--
Daniel C. Sobral

I travel to the future all the time.



--
Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang
andrevandelft
Joined: 2010-02-07,
User offline. Last seen 34 weeks 1 day ago.
Re: Units of Measurement — Scala Macros to the rescue?

Hello Simon,

It is good to aim for support physical dimensions without
a language extension. However, I think real good support
requires a limited change to the syntax and the compiler.
The syntax "Double[Time]" would be easier to achieve
than my old "double*Time" syntax.

Other things that the compiler should be made to understand could be:

trait Duration extends Dimension {val second}
trait Distance extends Dimension {val meter}
trait Speed = Distance / Duration

val kilometer: Int[Distance] = 1000 * meter

val v1= 3.0 * kilometer / second
val v2: Double[Speed] = 2.0 * v1
val v3 = v1 * v2
val v4: Double[Distance / Duration] = Math.sqrt(v3)

I am not sure whether base units such as meter and second should
be of type integer, float or double (or maybe even none of these).
In case of type integer, I would fear

val hour = 3600*second
val kmh = kilometer / hour // = 0

Cheers,

André

On 5 feb, 22:28, Simon Ochsenreither
wrote:
>
> I'm not sure I understand the remark about
> double*Time/Time[Double]/Double[Time] ... I'm using pure Scala, no language
> extension or compiler plugin. This rules out the first one. Also, Double is
> _the_ standard Scala/Java Double type, which has no type parameters, so I
> can't add any.

Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
Hi Andre,

It is good to aim for support physical dimensions without
a language extension. However, I think real good support
requires a limited change to the syntax and the compiler.
The syntax "Double[Time]" would be easier to achieve
than my old "double*Time" syntax.

I don't see what's the benefit of having something like Double[TIme], but I'm not even understanding the proposed semantics of it ... care to explain it a bit more in detail?

[code]

isn't that pretty much what I'm already doing?

What's the difference to the current situation?


In case of type integer, I would fear...

Yes, that's my concern, too. But in the end all numeric types are supported and I think having the "lifted" (Speed[Int]) types behave like the contained numeric types (Int) is intuitive. I'm open to better suggestions, though ...

Thanks,

Simon

Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
Hi Andre,

still there?

Bye,

Simon
andrevandelft
Joined: 2010-02-07,
User offline. Last seen 34 weeks 1 day ago.
Re: Units of Measurement — Scala Macros to the rescue?

Hello Simon,

Excuse me please for the delay.

About Double[Time] vs Time[Double]:
The first form, the dimension as a parameter of a
numeric type, has a more natural look and feel,
in my opinion (I am not 100% sure).
It would also be more natural when these
dimensions act as parameters for other types, e.g.,

class Computation[D1 <: Dimension, D2 <: Dimension] {

var a: Int[D1]
var b: Double[D2]
...
def result: Double[D1*D2] = a*b
}

The rules of the dimensioned numbers,
according to my paper:

- one specifies a set of base dimensions, together
with their associated base units, which will
become 1 after erasure

- the set of dimensions is an abelian group

- dimension aliases are allowed
e.g. "trait Speed = Distance / Duration"

- all other units are just dimensioned numbers

- addition and subtraction are always allowed
when one of the operands is a literal 0

- addition and subtraction are otherwise only
allowed when the operands have the
same dimensions

- multiplication and division yield the multiplied
or divided dimensions

- ToString is only allowed on dimensionless numbers

- casting (using "asInstanceOf") from a dimensioned
value to a dimensionless version is allowed,
and vice versa

Some concerns:

- should units be Integer or Float?
In case of Integer, km/hour would become
after erasure 1000/3600 = 0; maybe that could
be prevented somehow (but I doubt it).

- the square root function, and power functions

- vectors could hold numbers of only 1 dimension.

I don't think a restriction to, say, 7 SI base
dimensions with associated units would be good;
programmers will ask for additional ones, such as:

- angle, with radian as base unit
- information, with bit as base unit
- money (supposing that currencies are easily
interchangeable)
- US currency, european currency, …

These are my thoughts without worrying
too much about implementation: some changes
to Scala syntax would be needed.

There are good reasons for staying within the
current Scala syntax, so please don't let my
"wild ideas" paralyze you.

Cheers,

André

Martin S. Weber
Joined: 2008-12-23,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Units of Measurement ‹ Scala Macros to the rescue?

As usual, dimension checking isn't good enough. You'll need quantity
checking, and quantities aren't generally an abelian group. Especially in
the face of canceling exponents of dimensions in both numerator and
denominator of the dimensional expression. Classic examples include
dimensionless entities vs. e.g. Radian, Steradian and all quantities that
include angles (e.g. torque).

Regards,
-Martin

On 2012-02-09 04:24 , "André van Delft" wrote:

>Hello Simon,
>
>Excuse me please for the delay.
>
>About Double[Time] vs Time[Double]:
>The first form, the dimension as a parameter of a
>numeric type, has a more natural look and feel,
>in my opinion (I am not 100% sure).
>It would also be more natural when these
>dimensions act as parameters for other types, e.g.,
>
>class Computation[D1 <: Dimension, D2 <: Dimension] {
> Š
> var a: Int[D1]
> var b: Double[D2]
> ...
> def result: Double[D1*D2] = a*b
>}
>
>The rules of the dimensioned numbers,
>according to my paper:
>
>- one specifies a set of base dimensions, together
> with their associated base units, which will
> become 1 after erasure
>
>- the set of dimensions is an abelian group
>
>- dimension aliases are allowed
> e.g. "trait Speed = Distance / Duration"
>
>- all other units are just dimensioned numbers
>
>- addition and subtraction are always allowed
> when one of the operands is a literal 0
>
>- addition and subtraction are otherwise only
> allowed when the operands have the
> same dimensions
>
>- multiplication and division yield the multiplied
> or divided dimensions
>
>- ToString is only allowed on dimensionless numbers
>
>- casting (using "asInstanceOf") from a dimensioned
> value to a dimensionless version is allowed,
> and vice versa
>
>Some concerns:
>
>- should units be Integer or Float?
> In case of Integer, km/hour would become
> after erasure 1000/3600 = 0; maybe that could
> be prevented somehow (but I doubt it).
>
>- the square root function, and power functions
>
>- vectors could hold numbers of only 1 dimension.
>
>I don't think a restriction to, say, 7 SI base
>dimensions with associated units would be good;
>programmers will ask for additional ones, such as:
>
>- angle, with radian as base unit
>- information, with bit as base unit
>- money (supposing that currencies are easily
> interchangeable)
>- US currency, european currency, Š
>
>
>These are my thoughts without worrying
>too much about implementation: some changes
>to Scala syntax would be needed.
>
>There are good reasons for staying within the
>current Scala syntax, so please don't let my
>"wild ideas" paralyze you.
>
>Cheers,
>
>André

Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Units of Measurement — Scala Macros to the rescue?
Hi Andre!


The first form, the dimension as a parameter of a
numeric type, has a more natural look and feel,
Well, the current type signature more or less represents the implementation, there is nothing special about it.
 
- one specifies a set of base dimensions, together
  with their associated base units, which will
  become 1 after erasure
Basically I normalize them during construction, which is also a problem: "1mg? Bad luck, that's 0kg." I wonder if it would make sense to check that during construction ...

- the set of dimensions is an abelian group
mhhhh
 
- dimension aliases are allowed
  e.g. "trait Speed = Distance / Duration"
Yes, that's what's already happening.

- all other units are just dimensioned numbers
Yes.

- addition and subtraction are always allowed
  when one of the operands is a literal 0
No ... not sure if it would be worth the trouble (or even possible...)

- addition and subtraction are otherwise only
  allowed when the operands have the
  same dimensions
Yes, of course.
 
- multiplication and division yield the multiplied
  or divided dimensions
Yes, that too.
 
- ToString is only allowed on dimensionless numbers
I want to make toString work. I hope it is possible ...

- casting (using "asInstanceOf") from a dimensioned
  value to a dimensionless version is allowed,
  and vice versa
No, not planned. I provide toInt/toFloat/toLong/toDouble/... to convert to non-unit types, as well as asInt/asFloat/asLong/asDouble/... to convert the underlying type of the unit.
And probably value to just access the underlying value.

Some concerns:

- should units be Integer or Float?
  In case of Integer, km/hour would become
  after erasure 1000/3600 = 0; maybe that could
  be prevented somehow (but I doubt it).
Currently the units behave like the underlying units ...

- the square root function, and power functions
Yes, that will be tricky ... although square will be easier than a generic power function.

- vectors could hold numbers of only 1 dimension.

I don't think a restriction to, say, 7 SI base
dimensions with associated units would be good;
programmers will ask for additional ones, such as:

- angle, with radian as base unit
- information, with bit as base unit
- money (supposing that currencies are easily
  interchangeable)
- US currency, european currency, …
I think the question is to decide what's a practical feature set to ship, e. g. deciding on the right 80% without giving up the possibility to let people build their own extension.
In my opinion providing the basic scientific and documenting how to build the same functionality themselves is the right approach.

These are my thoughts without worrying
too much about implementation: some changes
to Scala syntax would be needed.

There are good reasons for staying within the
current Scala syntax, so please don't let my
"wild ideas" paralyze you.

Sure, I'm happy about every suggestion!

Thanks!

Simon
d_m
Joined: 2010-11-11,
User offline. Last seen 35 weeks 2 days ago.
Re: Re: Units of Measurement — Scala Macros to the rescue?

On Thu, Feb 09, 2012 at 02:57:36PM -0800, Simon Ochsenreither wrote:
> Yes, that will be tricky ... although square will be easier than a generic
> power function.

Just so you know, Tom Switzer and I are working on generic pow/nroot
implementations for Numeric currently.

See: https://github.com/non/scala-numerics-refactor

That package is not (yet) ready for prime time but hopefully will be
soon.

andrevandelft
Joined: 2010-02-07,
User offline. Last seen 34 weeks 1 day ago.
Re: Units of Measurement ‹ Scala Macros to the rescue?

Martin,

Strictly speaking, you are right. An energy is not a torque.
I think that dimension checking in the way I implemented
would still be useful. Support for quantity checking in a
programming language would be too hard, IMHO.
But I cannot really substantiate this; maybe someone can
come up with a good proposal.

Since you ended with torque, I'll quote Edsger Dijkstra.
His critique of the GREEN language submitted to the DoD
contains a fragment that inspired me to develop my Java
extension. GREEN was elected to become Ada, BTW.
Enjoy:

After having referred to the difficulties of the types in PASCAL,
they (= the GREEN authors, AvD) write (RAT p.1-8)
"These problems are overcome in the GREEN Language
with the notion of subtype." Are they?
They first explain the introduction of new types with

"type weight = integer; type length = integer"

which "define the new types "weight" and "length"
as different types, both distinct from the predefined type
"integer" although they have the properties of "integer"."

That is a very obscure sentence: if the new types have
all the properties of the old type, how can they differ?
They give two examples of assignment statements that
are supposed to explain this by their being invalid;
however "two "weights" or two "lengths" can be added
in the normal way". What is the type of such sums?
Presumably again "weight" or "length" respectively.
Are we allowed to multiply a "weight" with a "length",
and is the result a "torque"?

Source:
http://www.cs.utexas.edu/~EWD/transcriptions/EWD06xx/EWD660.html

On 9 feb, 20:26, "Weber, Martin S" wrote:
> As usual, dimension checking isn't good enough. You'll need quantity
> checking, and quantities aren't generally an abelian group. Especially in
> the face of canceling exponents of dimensions in both numerator and
> denominator of the dimensional expression. Classic examples include
> dimensionless entities vs. e.g. Radian, Steradian and all quantities that
> include angles (e.g. torque).
>
> Regards,
> -Martin
>
> On 2012-02-09 04:24 , "André van Delft" wrote:
>
> ...

andrevandelft
Joined: 2010-02-07,
User offline. Last seen 34 weeks 1 day ago.
Re: Units of Measurement — Scala Macros to the rescue?

On 9 feb, 23:57, Simon Ochsenreither
wrote:
> > - addition and subtraction are always allowed
> >   when one of the operands is a literal 0
>
> No ... not sure if it would be worth the trouble (or even possible...)

There are two good reasons to support a "polymorphic" 0
i.e. a zero that can be added to any dimensioned number:

First, from "0*x = 0" follows "0*meter = 0" etc.
Second, it is needed, e.g., in a function that summarizes
over a sequence of values that have a generic dimension:

def sum(values: Seq[Double[D<:Dimension]]): Double[D] = {
var result: Double[D] = 0.0
for (v<-values) result += v
result
}

Andrew Kennedy coined this polymorphic zero, about 18 years ago.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland