Non type-safe units
Opened this issue · 11 comments
(unit = "m", value = 42.0) / (unit = "s", value = 2.0) = (unit = ("/", "m", "s"), value = 21.0)
Values with a unit can be implemented as pair of MST of the special context and unit.
Possible benefits: valid unit shape, concise implementation.
Possible problem: lack of simplification of the shape.
MST-based units require additional considerations. On one hand, they are not compile-time type-safe, so they do not make sense in this regard. On the other hand, the context used to generate those units could provide runtime type unit check. Also with a staged compilation like one available in jupyter, it could be beneficial.
I think the main problem is that N*m ≠ m*N etc.
MST does not state that binary operation should be commutative. On the contrary, I would not expect that.
I mean units are not simplified to a certain comparable form
However, it is not such hard to implement such an algorithm - it is much easier than simplify a plain expression.
This issue is not about user level api. It is about generalization of symbolic processing of units. Measured is a nice way to use units and we do not want to dublicate it.
I've reworked the prototype without MST - units are stored as a product of base units.
import space.kscience.kmath.operations.RealField
import space.kscience.kmath.units.*
public fun main() {
var res = with(MeasurementExtendedField(RealField)) {
val a = (2.0 * kg) / (3.0 * m) / (2.0 * with(MeasureAlgebra) { s * s })
val b = (23.0 * Pa)
a + b
}
println(res)
res = with(MeasurementExtendedField(RealField)) {
val a = (2.0 * G(m)) + (3.0 * M(m))
val b = (3.0 * au)
a + b
}
println(res)
}
Measurement(measure=Measure(chain={SECOND=-2, METER=-1, KILOGRAM=1}, multiplier=1.0), value=23.333333333333332)
Measurement(measure=Measure(chain={METER=1}, multiplier=1.0), value=4.507966121E11)
Process finished with exit code 0
Actually, it is a dynamic analogue of Measured API.