Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Dimension type to Unit trait #367

Open
ttencate opened this issue Sep 1, 2022 · 4 comments
Open

Add Dimension type to Unit trait #367

ttencate opened this issue Sep 1, 2022 · 4 comments

Comments

@ttencate
Copy link

ttencate commented Sep 1, 2022

Related to #231, but I think it's complementary.

Right now, the generated Unit trait makes it difficult to write methods that work generically over different types of Units. For example:

fn do_work<N>(value: f64) -> Quantity<D, U, f64>
    where N: Unit
{
     Quantity::new::<N>(value) // Error! Cannot infer type of D and U
}

It would be great if some associated types could be added to the Unit trait:

pub trait Unit: Copy {
    /// The dimension of this unit.
    type Dimension: Dimension;
    /// The base units of this unit.
    type Units: Units;

    ...
}

So that we can write:

fn do_work<N>(value: f64) -> Quantity<D, U, f64> 
    where N: Unit
{
     Quantity::<N::Dimension, N::Units, _>::new::<N>(value)
}
@iliekturtles
Copy link
Owner

This would possibly be handled by #91, but I'm going to leave open as a separate request for the time being.

@iliekturtles
Copy link
Owner

Back in 2019 I had big plans to solidify the current uom into a 1.0 release. Based on current limitations (#91) I had also started working through a new API that would eventually become 2.0. You can see my efforts in the dev-macros branch (I was also looking at moving to procedural macros). One of things the new API does do is make Dimension and associated type of Unit.

uom/src/lib.rs

Lines 272 to 275 in 020e421

pub trait Unit {
type D: Dimension + ?Sized;
type K: ?Sized;
}

Besides being really busy, part of the reason I haven't made progress is that the limitation of what is in that branch is that the output type needs to be specified for any multiply or divide operations. I'm also not sure if procedural macros is the appropriate way forward or if some kind of pre-compile codegen is more appropriate.

@ttencate
Copy link
Author

ttencate commented Sep 8, 2022

Not sure I understand. I tried writing my own similar library that carried a unit along with each value, but ran into a similar limitation. There is no way to know at compile time that kilometer divided by hour makes the unit type kilometer_per_hour. But the way uom works, multiply/divide just works on base units, right? At least D is just computed from the inputs; I don't know what K is in the above snippet.

@iliekturtles
Copy link
Owner

Yes, uom normalizes values down to the 7 base units (defaults can be overridden by ISQ!). K distinguishes the quantity's kind. A notable example is thermodynamic temperature/temperature interval (ratio/angle is another example). Both quantities have the same dimension but different kinds and you don't want to mistakenly add the two together.

uom/src/si/mod.rs

Lines 22 to 44 in 7c4b27b

quantities: ISQ {
/// Length, one of the base quantities in the ISQ, denoted by the symbol L. The base unit
/// for length is meter in the SI.
length: meter, L;
/// Mass, one of the base quantities in the ISQ, denoted by the symbol M. The base unit
/// for mass is kilogram in the SI.
mass: kilogram, M;
/// Time, one of the base quantities in the ISQ, denoted by the symbol T. The base unit
/// for time is second in the SI.
time: second, T;
/// Electric current, one of the base quantities in the ISQ, denoted by the symbol I. The
/// base unit for electric current is ampere in the SI.
electric_current: ampere, I;
/// Thermodynamic temperature, one of the base quantities in the ISQ, denoted by the symbol
/// Th (Θ). The base unit for thermodynamic temperature is kelvin in the SI.
thermodynamic_temperature: kelvin, Th;
/// Amount of substance, one of the base quantities in the ISQ, denoted by the symbol N.
/// The base unit for amount of substance is mole in the SI.
amount_of_substance: mole, N;
/// Luminous intensity, one of the base quantities in the ISQ, denoted by the symbol J. The
/// base unit for luminous intensity is candela in the SI.
luminous_intensity: candela, J;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants