In the time library ( 
package.elm-lang.org/packages/elm-lang/core/4.0.3/Time ), there are many 
functions under the "Units" heading. Under the function `millisecond`, it 
says:
>Units of time, making it easier to specify things like a half-second (500 
* millisecond) without remembering Elm’s underlying units of time.
I find this underwhelming, because nothing forces me to use these unit 
functions. I could write `every 5 toMsg` and the compiler will not stop me. 
How long of a time am I actually specifying? Probably 5 milliseconds, 
because I infer that it's probably using the same unit as JavaScript, but I 
can't know for sure. A beginner might think 5 seconds, because it's the 
unit that has no prefixes, or 5 minutes if 5 minutes seems appropriate to 
what the application does. This is very bad; There should never be doubt 
about what unit is being used, and the compiler should enforce this unit 
correctness. Currently, Elm can't do this, because `Time` is just an alias 
for `Float`.

To prevent this kind of error, I propose a new language construct that I 
call a "unit type". It would have the following properties:
(1) A definition that would look (very roughly) like this:
```
type unit Time as Float
    = Second
    | Millisecond == Second 0.0001
    | Nanosecond == Millisecond 0.0001
    | Minute == Second 60
    | Hour == Minute 60
    | Day == Hour 24
    | Year == Day 365
```

The point of the definition is to:
(a) Provide an easy way to define different units that measure the same 
thing (in this case, time, but you could do the same thing for 
length/height/depth in either metric or US imperial units) as constructors.
(b) Tell how they are related to eachother. (A minute is 60 seconds, an 
hour is 60 minutes, etc.) The compiler would check that all relations of 
the constructors eventually flow to a single base unit (in this case, 
`Second`). A cycle would be disallowed.
(c) Tell what type the unit is based on (in this case, `Float`). (Perhaps 
non-number types would be disallowed.)

(2) Given that `every` still has the same signature: `Time -> (Time -> msg) 
-> Sub msg`, `every 5 toMsg` would cause a compile-time error, because the 
types don't match; The function expects a number with a `Time` unit, but 
receives `5`, which is just a raw number (a number without any unit).
(3) When writing a function that has a parameter of type `Time`, pattern 
matching only matches the base unit constructor, not every constructor like 
a normal (data/enum) type. The compiler would automatically convert the 
other units to the base unit with the conversions that the programmer 
provided in the definition.
(4) Comparison, addition, and subtraction would be automatically 
implemented for the type, so two times of any combination of constructors 
could be compared, added, or subtracted with ease. `(Minute 5) - (Second 
20) == (Millisecond 280000)` would "just work". "Time + Float" (or "Time + 
Length") would cause a compile-time error.
(5) Perhaps compound unit types like "Time^2" would be supported, so a 
"Time * Time" would yield "Time^2", "Time * Float" would yield "Time", and 
"Time * Length" would yield just that: "Time * Length". ("Force" would be 
an alias of "Mass * Length / (Second^2)".)

I know that this is a very radical proposal, (I don't know of any language 
that has a feature like this.) but I bring it up anyways, because although 
it's been 18 years since the mars probe crashed because of a unit error 
(one module assumed that the number it was getting was in metric units, and 
another assumed that it was getting it in US imperial units) ( 
https://en.wikipedia.org/wiki/Mars_Climate_Orbiter ), I'm amazed that since 
then, programming languages have done nothing to prevent this kind of error 
from happening again, besides just admonishing programmers to be careful. 
(As if the NASA programmers at the time weren't already trying to!)

Letting `5` be a legal unitless `Time` value is just as silly and dangerous 
as letting `bool a = 2;` be a legal statement in C. data/enum types prevent 
this from happening to `Bool` in Elm, and unit types could prevent the same 
kind of thing from happening to `Time`.

Questions, comments, related thoughts, etc are welcome.

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to