Add more quantity types
ianmackenzie opened this issue ยท 49 comments
Here's a list of modules that I'd like to add at some point - pull requests for any of these are welcome! (Take a look at existing modules for inspiration.) I've listed how I think each quantity's units should be defined, either as a base unit (Moles
, Candelas
, etc.) or as a rate/product of other units (in which case the units type will be a type alias of the form Rate x y
or Product x y
). Note that there are some dependencies here - can't add the VolumetricFlow
modules without the Volume
module, or LuminousIntensity
without SolidAngle
!
Kinematics/dynamics
-
AngularSpeed
(RadiansPerSecond = Rate Radians Seconds
) (thanks @katjam!) -
AngularAcceleration
(RadiansPerSecondSquared = Rate RadiansPerSecond Seconds
) (thanks @katjam!) -
Torque
(NewtonMeters = Product Newtons Meters
) (thanks @gampleman!)
Volume
-
Volume
(Cubed Meters
) (thanks @katjam!) -
VolumetricFlow
(CubicMetersPerSecond = Rate CubicMeters Seconds
) -
Density
(KilogramsPerCubicMeter = Rate Kilograms CubicMeters
) (thanks @katjam!) -
SubstanceAmount
(Moles
) (thanks @ukarim!) -
Molarity
(MolesPerCubicMeter = Rate Moles CubicMeters
) (claimed by @lenards)
Electromagnetism
-
Inductance
(Henries = Rate Volts (Rate Amperes Seconds)
) (thanks @ukarim!) -
Capacitance
(Farads = Rate Coulombs Volts
) (thanks @ukarim!)
Photometry
-
SolidAngle
(Steradians
) -
LuminousFlux
(Lumens
) -
LuminousIntensity
(Candelas = Rate Lumens Steradians
) -
Illuminance
(Lux = Rate Lumens SquareMeters
) -
Luminance
(Nits = Rate Candelas SquareMeters
)
@ianmackenzie Thanks for the call out... I've set aside some days this month to contribute to hacktoberfest.
Not wishing to double up efforts with others - shall I have a go at Volume for starters? I think my maths will cope.
@katjam Sure, sounds good, and thanks for checking first! Off the top of my head for volume units I'd suggest including (along with cubicMeters
):
liters
,milliliters
usLiquidGallons
,usDryGallons
,imperialGallons
usLiquidQuarts
,usDryQuarts
,imperialQuarts
usLiquidPints
,usDryPints
,imperialPints
usFluidOunces
,imperialFluidOunces
Gotta love crazy non-metric units! In general I've tried to make all conversion constants in the elm-units
source code exact, even if that means dividing by a constant or multiplying by a chain of constants instead of multiplying by a single constant. To the extent that this is possible for all the above units, that would be ideal.
It would be kinda nice to also include cooking units like teaspoons, tablespoons and cups, but those seem to vary wildly between countries without even standard names for the different versions, so I'd say leave them out.
Perfect. I'm getting Errors regarding comparable type in Quantity module when I try to compile. Is that expected?
e.g.
-- TYPE MISMATCH ------------------------------- ./../elm-units/src/Quantity.elm
The 1st argument to function `min` is causing a mismatch.
276| Basics.min x y)
^
Function `min` is expecting the 1st argument to be:
comparable
But it is:
number
Hint: Only ints, floats, chars, strings, lists, and tuples are comparable.
Yes - cooking units do seem to vary - maybe could identify differences by country code but I'll leave for now.
That's interesting, I don't get that compile error myself (even if I explicitly call Quantity.min
) - you're not using Elm 0.18 or something, are you?
Oops! I'll upgrade. :)
It would be kinda nice to also include cooking units like teaspoons, tablespoons and cups, but those seem to vary wildly between countries
Huh, I always thought one teaspoon was 5ml and a tablespoon was 15ml. A quick wikipedia search tells me that:
- US tablespoon is ~ 14.8ml
- Australian tablespoon = 20ml
- Metric tablespoon = 15ml
- probably more...
๐ฐ ๐ฐ ๐ฐ
I'm kind of surprised it even started compiling in 0.18 (hence my skepticism that that was the issue), given that there's no elm-package.json
, just the new elm.json
...but I guess if you were just compiling individual files or something maybe that works without a package file.
@JoelQ yeah, that's the Wikipedia page I was looking at when I basically threw my hands up and said "forget it". Fortunately it would be easy enough for someone else to create separate Cooking.US
and Cooking.Australian
etc. modules (in a separate package) with functions like tablespoons : Float -> Volume
etc...but I think those are sufficiently fuzzy and ill-defined that they don't belong in the base elm-units
package.
If there is one thing I have learned when making this package, it is that anything other than an SI unit is very likely to have multiple slightly-different versions in common, modern use. Tablespoons, gallons, horsepower, tons...
I made a little project that includes elm-units
so I'd be more confident testing stuff.
I've sorted out the elm version issues - good excuse to upgrade my other projects too. :)
Yeah units are nuts. I guess cultures like to define their own standards.
Ahhh OK, that makes sense - so you were just including elm-units
via source-directories
from an Elm 0.18 project. Interesting that Elm 0.19 accepts that min
code and Elm 0.18 doesn't! I guess there were some subtle changes to comparable
to accept generic number
values and not just specific Float
or Int
...I don't remember that being mentioned anywhere but I guess it would only affect a tiny number of use cases.
I had a quick google before I asked you too - because I thought maybe it was an 0.18 to 0.19 thing - but nada.
Anyway - all good now. Nearing supper time for me - but hopefully have something up tomorrow. I've taken scattered days off work this month so may be fits and starts.
No rush! I may very well end up releasing 1.0 with just the existing modules (I was planning on an initial release this week), but it was always the plan to steadily add more modules in minor releases post-1.0. So if you finish in a week or two there's no reason we couldn't immediately publish a 1.1.
Sounds good. ๐
Going to have trouble remembering to spell metres
'correctly' though. ๐
Hahaha fair point! I'm Canadian myself, and I do realize that 'metres' is the standard SI spelling of the unit. But it seems that American spelling (color etc.) is the de facto standard in programming, so I decided a long time ago to follow that for all my programming projects. It helps that American spellings tend to be a bit simpler (color vs colour) and more phonetic (meters vs metres), so it feels like an objectively reasonable choice and not just surrendering to the majority.
It heartens me to find out that the American spellings were due to a considered, deliberate effort to make spelling simpler and more regular: https://www.businessinsider.com/spelling-american-vs-british-noah-webster-2018-3
I think as programmers we can all appreciate a nice simplifying refactor!
Am I on the right track? Added cubed and cbrt to Quantity though not sure if you think it's helpful since not supported by Basics
Looking pretty good! I have a few small thoughts/comments/questions but I think it would make sense to just open a pull request and we can discuss there - it's totally fine to open a pull request with partial work, you can keep pushing to your branch and those changes will show up in the pull request. But that way we can have a discussion there (and I can in fact go in and make small changes to your branch myself) without adding too many more comments to this issue.
Do you have a next priority in mind for the others? I'm happy to tackle any - once #9 goes in.
Awesome! I think AngularSpeed
would probably be the next most fundamental (I can see that being useful for things like animations), and then perhaps AngularAcceleration
for completeness. After that, maybe Density
?
I'm personally most excited about the photometric units (I'm working on a 3D rendering package and I'd love to be able to specify lights in physical units like Lumens
), but those are also by far the most confusing/mind-bending of the bunch - I'm still wrapping my head around Luminance
vs Illuminance
.
I'll go for AngularSpeed
then.
Sounds good! I'm a bit conflicted on naming there - radiansPerSecond
and degreesPerSecond
seem obvious enough, and turnsPerSecond
would then be consistent, but I'd also like to have revolutionsPerMinute
(to match common usage) instead of turnsPerMinute
. Could just switch to revolutions
everywhere (including in the Angle
module), but then that would be breaking with the names in the core Basics
module...
I'll stick up a stub PR in a bit so we can continue the conversation there.
Philosophically - I prefer revolutions to (taking) turns...
I'll go for AngularAcceleration
next.
Sounds good! I think for AngularAcceleration
you could probably leave out revolutions per minute entirely - doesn't seem clear whether the corresponding acceleration unit would be revolutions per minute per minute or revolutions per minute per second. And any weird angular acceleration values like that can be constructed using Quantity.per
anyways.
I'll go for Density
next.
No promises on how fast I'll get to it, but I still have some time to take off work between now and Christmas... what's the next priority?
No promises on how fast I'll get to it, but I still have some time to take off work between now and Christmas... what's the next priority?
I'd be inclined to look at #10 and/or #19 next...either immediately start in on refactoring to use a Constants
module (using the existing constant values), or look through the NIST/UK/DIN references and check:
- if there are any units in
elm-units
that aren't listed in at least one of those sources - if there are any cases where a unit in
elm-units
has conflicting definitions in those sources
Thanks so much for all your continued contributions!
Thanks for letting me help. It's nice to have a project outside of work & personal to focus on. I guess it makes sense to do #19 with existing and then tidy it up with #10 if we need to alter anything?
I'll let you know before I start - making an initial WIP PR so we don't double up. Until I do - which should be within the next couple of weeks, you can assume I've done nothing.
Sounds good! I'll probably be focusing on elm-geometry
for the next little while (just started a big refactor there), so I don't anticipate any conflicts.
@ianmackenzie - are Molarity
, Torque
, and VolumetricFlow
still desired?
Hi @lenards yes, certainly! And I'm not aware of anyone else working on them if you want to start a PR =)
@lenards @ianmackenzie It's probably also a good time for me do some more stuff. Let me know where I can be most useful.
I'll take a crack at Molarity
!
I'll go for Torque
. It'll be nice to get this issue completed.
Thanks both! And yes it will be great to be able to close this one =)
Is it ok if I take VolumetricFlow? That one looks unclaimed. It would be a great way for me to get into some Elm!
@jamessral please do! I'll update the issue.
@lenards you may not be missing anything - it's entirely possible that there really are only one or two common ways of specifying molarity, I haven't really looked into it myself. If you want to open a PR with the basic constructor and in
function and any interesting references you consulted, I'm happy to take a look.
I'm progressing on Molarity
and additional definitions for SubstanceAmount
.
@ianmackenzie Finally made some time to look at Torque
. As per your description, I will define in terms of NewtonMeter
, but do you think we should reference JoulePerRadian
also or at least export a set of alias functions like we do in AngularSpeed
for turns vs revolutions?
From my initial reading they are equally valid units - my simple understanding is that since Radian
is unitless, JoulePerRadian
is mathematically equivalent to NewtonMeter
but conceptually different.
Please don't feel the need to take time out to explain. I can read more if I need to - just wanted to know if you want me to reference the Joule
relationship in any way.
@katjam I think it's probably fine to leave out joules per radian for now (I think it's a different situation than angular speed - at least there everything is still conceptually "amount of rotation per unit time", just with different terminology).
There's a broader question here about how to deal with different, equivalent forms of the same quantity type - see #32.
Would it make sense to add hertz? I'm working on an audio package and hertz seems like an appropriate unit for describing the sample rate of a sound file.
Interesting! What operations do you think you'd want to perform on a Frequency
value? I think the easiest would be to define Frequency
as Quantity Float Hertz
and Hertz
as Rate Unitless Float
, but it's not immediately obvious whether that would be a useful representation for the kinds of operations you might want to perform on frequencies.
For me it would probably be used in type alias AudioContext ={ sampleRate: Frequency }
, samplesToDuration: AudioContext -> Quantity Int Samples -> Duration
, and durationToSamples: AudioContext -> Duration -> Quantity Float Samples
.
In other words, for my use case I can just write ~10 lines of code and have everything I need. I figured it was worth bringing up though because Frequency/Hertz seems to be a commonly used unit and I was surprised to not see it included here.
Would it work in your case to define something like
type alias SamplesPerSecond =
Rate Samples Seconds
type alias SampleRate =
Quantity Float SamplesPerSecond
? Then durationToSamples
is basically duration |> Quantity.at context.sampleRate
(or equivalently context.sampleRate |> Quantity.for duration
) and samplesToDuration
is basically Quantity.toFloatQuantity numSamples |> Quantity.at_ context.sampleRate
. Or is that what you meant by the ~10 lines?
I guess it just seems that in many cases (like this one) it makes sense to have a unit (like Samples
) associated with a frequency, instead of Frequency
being its own standalone quantity type. We could have it be a special quantity type that had its own type parameter, like
module Frequency exposing (Frequency)
type alias Frequency units =
Quantity Float (Rate units Seconds)
but in a lot of ways it seems simpler just to treat it like a generic rate quantity.
Yeah, that's what I meant by 10 lines. It's not that Frequency
/Hertz
missing from elm-units
is a problem for me. It's more that I figured this is an important kind of quantity that should be in elm-units
.
As you mention though, it seems like Frequency doesn't need to be a standalone quantity as it can be represented with Rate
. I think that answers my question then as to why I didn't see Frequency
/Hertz
present then.