elm-units
elm-units copied to clipboard
Add support for non-negative units
The Quantity
API allows for the wrapped value to be any numeric value. In some cases, units that are less than zero are not possible, and it would be nice to make impossible states impossible in those cases.
One way to accomplish this would be to introduce a new type (e.g. AbsoluteQuantity
) which enforces that its value is always non-negative via its API.
My specific use case involves measuring periods of time, and
type alias TimeBlock = { start: Time.Posix, duration = Duration.Duration }
allows for impossible states when the duration is negative, but
type alias TimeBlock = { start: Time.Posix, duration = <non-negative duration type here> }
does not.
I think a new type like NonNegativeQuantity
would be tricky, since then you'd presumably need NonNegativeDuration
, NonNegativeLength
etc. types/modules, with a bunch of duplicate logic to create a new NonNegativeDuration
from a non-negative value in seconds, minutes, hours etc. - it would basically be a full separate copy of the elm-units
API.
One possibility might be to (ab)use the first type parameter of Quantity
to use an underlying non-negative numeric type (e.g. a hypothetical NonNegativeFloat
type, published as an independent package). By itself that wouldn't be super useful since you wouldn't be able to use any of the functions in (e.g.) the Duration
module, but if we added something like
Quantity.map : (a -> b) -> Quantity a units -> Quantity b units
then you could do something like Quantity.map NonNegativeFloat.toFloat myNonNegativeQuantity
to get a 'normal' quantity that you could do math with. (I'd be open to adding map
, map2
etc. functions - they're a little unsafe since they would provide a pretty easy way to subvert units safety, but I can see them being pretty useful in some cases.)