-
Notifications
You must be signed in to change notification settings - Fork 14
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 functions to convert between different forms of the same quantity type #32
Comments
Non-breaking version: keep units the same (one canonical units type per quantity type), but for uniformity support functions like Force.massTimesAcceleration mass acceleration could be written as mass |> Quantity.times acceleration Then also provide Call these functions "constructors" and "reinterpretations"? |
For the 'constructors', should they be of the form Speed.lengthPerDuration : Quantity Float (Rate Meters Seconds) -> Speed
-- e.g.
Speed.lengthPerDuration (Length.kilometers 100 |> Quantity.per (Duration.hours 1)) or Speed.lengthPerDuration : Length -> Duration -> Speed
-- e.g.
Speed.lengthPerDuration (Length.kilometers 100) (Duration.hours 1) ? The latter is more convenient for simple cases but is asymmetric with Speed.asLengthPerDuration : Speed -> Quantity Float (Rate Meters Seconds) and is less flexible since it forces the caller to pass separate values (which could be annoying if they get a Speed.lengthPerDuration : Length -> Duration -> Speed
Speed.fromLengthPerDuration : Quantity Float (Rate Meters Seconds) -> Speed
Speed.toLengthPerDuration : Speed -> Quantity Float (Rate Meters Seconds) |
I have been playing around with some functions that practically do nothing to the value other than change its signature. I think it may be useful to define some operations that transform the complex signatures (combinations of lift :
Area
-> Quantity Float Unitless
-> Density
-> Speed
-> Force
lift wingArea liftCoefficent airDensity speed =
squared speed
-- ((L/T)(L/T))
|> normalizeRR
-- ((LL)/(TT))
|> times airDensity
-- (((LL)/(TT))(M/((LL)L))
|> normalizeRR
-- (((LL)M)/((TT)((LL)L)))
|> onRate flip flip
-- ( (M(LL)) / ( ((LL)L)(TT) ) )
|> onRate identity shiftRight
-- ( (M(LL)) / ( (LL)(L(TT)) ) )
|> simplifyPP
-- ( M / (L(TT)) )
|> times wingArea
-- (( M / (L(TT)) )(LL))
|> normalizeRN
-- ((M(LL))/(L(TT)))
|> onRate shiftLeft identity
-- (((ML)L)/(L(TT)))
|> simplifyPP
-- ((ML)/(TT))
|> extractFirst
-- (M(L/(TT)))
|> onProduct identity extractLast
-- (M((L/T)T))
|> apply liftCoefficent
|> half
normalizeRR :
Quantity number (Product (Rate a b) (Rate c d))
-> Quantity number (Rate (Product a c) (Product b d))
normalizeRR =
repackage
normalizeRN :
Quantity number (Product (Rate a b) c)
-> Quantity number (Rate (Product a c) b)
normalizeRN =
repackage
simplifyPP :
Quantity number (Rate (Product a b) (Product b c))
-> Quantity number (Rate a c)
simplifyPP =
repackage
onRate :
(Quantity number a -> Quantity number c)
-> (Quantity number b -> Quantity number d)
-> Quantity number (Rate a b)
-> Quantity number (Rate c d)
onRate _ _ =
repackage
onProduct :
(Quantity number a -> Quantity number c)
-> (Quantity number b -> Quantity number d)
-> Quantity number (Product a b)
-> Quantity number (Product c d)
onProduct _ _ =
repackage
flip :
Quantity number (Product a b)
-> Quantity number (Product b a)
flip =
repackage
shiftRight :
Quantity number (Product (Product a b) c)
-> Quantity number (Product a (Product b c))
shiftRight =
repackage
shiftLeft :
Quantity number (Product a (Product b c))
-> Quantity number (Product (Product a b) c)
shiftLeft =
repackage
extractFirst :
Quantity number (Rate (Product a b) c)
-> Quantity number (Product a (Rate b c))
extractFirst =
repackage
extractLast :
Quantity number (Rate a (Product b c))
-> Quantity number (Rate (Rate a b) c)
extractLast =
repackage
repackage : Quantity number a -> Quantity number b
repackage (Quantity value) =
Quantity value
-- multiplies a unit with a `Unitless` value without altering the original signature
apply : Quantity Float Unitless -> Quantity number unit -> Quantity number unit
apply (Quantity value) =
Quantity.multiplyBy value the tough part is actually figuring out and covering all the required atomic operations, as well as finding good names for them (a classic) On the other hand, this is too much noise for the signal. |
@edgerunner sounds like you're doing some pretty sophisticated stuff with lift : Area -> Quantity Float Unitless -> Density -> Speed -> Force
lift (Quantity wingArea) (Quantity liftCoefficent) (Quantity airDensity) (Quantity speed) =
Quantity (0.5 * speed ^ 2 * airDensity * wingArea * liftCoefficient) as discussed here. Yes, you do have to be careful to make sure that the expression inside the The original plan for That said, if there are some additional kinds of multiplication/division operations that we can come up with good names for, then I'm open to adding those. One final note - you could write apply factor quantity as Quantity.multiplyBy (Quantity.toFloat factor) quantity if you wanted to avoid an extra helper function - I think that's the only one of those functions that could be rewritten in terms of existing |
Another potentially interesting approach could be to have a single |
At one point I was thinking of coercing the base unit types into a single union type which also includes combinators I gave that idea up because there was no way of converting that back to one of the That approach could be used in something like |
Oops please ignore that last comment (now deleted), I meant to comment on #62. That'll teach me to try to do GitHub work on my phone 😅 |
All just no-ops that just convert between equivalent units types:
Force.energyPerLength : Quantity Float (Rate Joules Meters) -> Force
Force.asEnergyPerLength : Force -> Quantity Float (Rate Joules Meters)
Energy.massTimesSpeedSquared : Quantity Float (Product Kilograms (Squared MetersPerSecondSquared)) -> Energy
Energy.asMassTimesSpeedSquared : Energy -> Quantity Float (Product Kilograms (Squared MetersPerSecondSquared))
Possible breaking change: perhaps then switch back to
Force
,Energy
etc. having their own units types, e.g.instead of
and then always convert to/from rates/products where needed. More symmetric (doesn't 'bless' one particular representation as the canonical one), and perhaps less confusing - always need to cast to a rate/product if you need one. In this case we would also need
Force.massTimesAcceleration : Quantity Float (Product Kilograms MetersPerSecondSquared) -> Force
Force.asMassTimesAcceleration : Force -> Quantity Float (Product Kilograms MetersPerSecondSquared)
Energy.forceTimesLength : Quantity Float (Product Newtons Meters) -> Energy
Energy.asForceTimesLength : Energy -> Quantity Float (Product Newtons Meters)
The text was updated successfully, but these errors were encountered: