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

Arbitrary "annotations" to units #611

Open
joshop opened this issue Oct 10, 2024 · 3 comments
Open

Arbitrary "annotations" to units #611

joshop opened this issue Oct 10, 2024 · 3 comments
Labels

Comments

@joshop
Copy link

joshop commented Oct 10, 2024

A common thing I find myself mentally inserting into calculations is the type of quantity that a unit corresponds to. For example, if we have the chemical equation 4Fe + 3O₂ → 2Fe₂O₃, and we want to know how much Fe₂O₃ is produced from 10 g of Fe. I might type something like 10 g / (55.485 g/mol) / (4 mol / mol) * (2 mol / mol) * (159.69 g/mol), but in my head I'm thinking 10 g of Fe, 55.485 g of Fe per mol of Fe, ... What if Numbat could track these "annotations" too? Here is how I envision it working:

  • Any unit can have any alphanumeric annotation added to it, no need to define beforehand. These don't affect the behavior of the unit in any specific way. (I'm not suggesting any particular syntax for it below, it's just a placeholder)
  • The type checker would try to uphold unit annotations, so g_Fe and g_Ag can't be added directly, etc. Perhaps it should be possible to explicitly convert between them, though. Or, if you'd prefer, just encourage structures like (g_Ag / g_Fe), which is intuitive.
  • Operations that don't involve the annotation are valid and preserve it: 5 mol_Ar * (22.41 L/mol) = 112.05 L_Ar and so on. This might lead to weird behavior (like 10 g_Fe / g = 10 _Fe - what does that mean??) so this could be left unimplemented.
@sharkdp
Copy link
Owner

sharkdp commented Oct 23, 2024

Thank you for writing this down. I think this is a really interesting feature! I have thought about it in the past — but in a slightly different way. I think what you're asking for is pretty similar to quantity kinds in the mpunits library. Being able to differentiate between "width" lengths and "height" lengths, is similar to differentiating between "Fe" grams and "Ag" grams.

  • Any unit can have any alphanumeric annotation added to it, no need to define beforehand.

I see how that could be handy, but maybe it would be better to make this explicit. And before we think about units, we need to think about types. We would probably introduce something like Mass["Fe"], and we would need to think about its properties w.r.t. Mass and other Mass["…"] types.

  • Perhaps it should be possible to explicitly convert between them, though. Or, if you'd prefer, just encourage structures like (g_Ag / g_Fe), which is intuitive.

See also: https://mpusz.github.io/mp-units/2.3/users_guide/framework_basics/systems_of_quantities/#converting-between-quantities

Operations that don't involve the annotation are valid and preserve it: 5 mol_Ar * (22.41 L/mol) = 112.05 L_Ar and so on.

Hm. I'm not sure how that would work?

@joshop
Copy link
Author

joshop commented Oct 25, 2024

Implementing something like the system of quantity kinds would be a very helpful feature, but I was envisioning something that you could adapt for any purpose - like elements/materials here, which it would be very impractical to formally list. Either way, implementation would probably be somewhat similar but unfortunately I can't really speak to implementation details with regard to the type system.
Now that I've been thinking, though, there are some tricky questions to answer as to operations here:

  • Volume: what is 1 cm_Fe * 1 cm_Fe * 1 cm_Fe? Is it 1 (cm_Fe)^3, or 1 cm^3_Fe, or something weird like 1 cm^3_Fe^3?
  • Ratios: what is 5 g_Fe / 10 g_Al? Is it just 0.5, or 0.5 Fe/Al or something else weird like that? This could reasonably represent a relation between the quantities of two materials
  • Mixing: should 1 kg_Fe * 1 kg_Al even be possible? Should the annotation of the result be Fe, or Al, or Fe*Al, or nothing?
  • Shifting the annotation: should we be able to do something like 1 mol_Ar * (22.41 L/mol)? If this was possible, would "move" the annotation from mol to L, or just discard it? What about something more clear, like 1 mol_Ar * (22.41 L_Ar / mol_Ar)?
    Obviously there are some weird semantics here, so it may be best to simplify this system, or maybe reduce it to something like the quantity kinds you mentioned.

@sharkdp
Copy link
Owner

sharkdp commented Dec 27, 2024

Any unit can have any alphanumeric annotation added to it, no need to define beforehand. These don't affect the behavior of the unit in any specific way. (I'm not suggesting any particular syntax for it below, it's just a placeholder)

yes

The type checker would try to uphold unit annotations, so g_Fe and g_Ag can't be added directly, etc. Perhaps it should be possible to explicitly convert between them, though. Or, if you'd prefer, just encourage structures like (g_Ag / g_Fe), which is intuitive.

yes

Operations that don't involve the annotation are valid and preserve it: 5 mol_Ar * (22.41 L/mol) = 112.05 L_Ar and so on.

This sounds like a reasonable simplification. Because one would want to use predefined constants/units involving mol/g etc. in un-annotated form.

So if we want this as well, then we should only support it if it's unambiguous. So maybe if you only have mol_Ar and mol in an expression, they act the same. But if you have mol_Ar, mol_Fe and mol, they would be three separate things for "safety reasons".

I see how that could be really confusing and maybe even error-prone though.

This might lead to weird behavior (like 10 g_Fe / g = 10 _Fe - what does that mean??)

In the above sense, 10 g_Fe / g could be just 10.

  • what is 1 cm_Fe * 1 cm_Fe * 1 cm_Fe? Is it 1 (cm_Fe)^3, or 1 cm^3_Fe, or something weird like 1 cm^3_Fe^3?

1 (cm_Fe)^3

Ratios: what is 5 g_Fe / 10 g_Al? Is it just 0.5, or 0.5 Fe/Al or something else weird like that? This could reasonably represent a relation between the quantities of two materials

I think this should just be 5 g_Fe / 10 g_Al. If we simplify here, then we give up type safety completely?

Mixing: should 1 kg_Fe * 1 kg_Al even be possible? Should the annotation of the result be Fe, or Al, or Fe*Al, or nothing?

Similar, this should not simplify and just stay 1 kg_Fe * kg_Al.

  • should we be able to do something like 1 mol_Ar * (22.41 L/mol)? If this was possible, would "move" the annotation from mol to L, or just discard it?

Hm. I would propose we don't "move" it, but rather "spread" the annotation to all appearances of mol. L would stay un-annotated.

  • What about something more clear, like 1 mol_Ar * (22.41 L_Ar / mol_Ar)?

This should simplify to 22.41 L_Ar?

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

No branches or pull requests

2 participants