Re: [elm-discuss] Re: Unit Types : A Radical Proposal

2016-08-04 Thread John Bugner
I just realized that Elm already uses this strategy... with `Color`! It has 
two constructors: RGBA and HSLA ( 
https://github.com/elm-lang/core/blob/master/src/Color.elm ), but neither 
is exported. This forces the user to use the various 'creation' functions 
to create one ( 
http://package.elm-lang.org/packages/elm-lang/core/4.0.4/Color ). There's 
no reason why the same thing couldn't be done with an `Angle` type. All the 
trig functions and angle creation functions in `Basics` should probably be 
moved to a new `Angle` module too then.

On Friday, July 29, 2016 at 11:55:35 AM UTC-5, Duane Johnson wrote:
>
>
> On Fri, Jul 29, 2016 at 10:48 AM, Anton Lorenzen  > wrote:
>
>> I just created a small library for this:
>> https://github.com/anfelor/elm-units
>>
>> It allows for time to be used like this:
>> Units.Time.every (30 ::: milliseconds) Tick
>>
>
>
> Neat! I'm surprised at what can be done with existing syntax and types.
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-30 Thread Job van der Zwan
On Thursday, 28 July 2016 20:42:44 UTC+2, John Bugner wrote:
>
> (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)".)
>

Here's how Julia handles this, although it seems to require hand-coding all 
of of the promotion rules:

http://docs.julialang.org/en/release-0.4/devdocs/promote-op/

(understanding this may require a bit of understanding Julia's type system, 
which lets you define your own types down to the bit-level 
, complete with custom 
conversion and promotion rules 
)

Not sure how that might translate to Elm's type system, but I guess using 
custom infix operators will be part of it (except for not allowing 
redefining the built-in ones). Off-topic, but is this really all 
documentation available on infix operators? Because I don't really think 
that's good enough:

http://elm-lang.org/docs/syntax#infix-operators 

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-29 Thread Max Goldstein
Just be careful with (:::) in particular. Some other libraries already define 
it, and there's currently no good way to resolve conflicts. 

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-29 Thread John Bugner
Btw, when using (:::) this way, it's nice to set the operator precedence to 
something lower than 9 so you can say `2 * 5 + 3 ::: radians` without 
having to put brackets around the numbers. I think `infix 5 :::` gives the 
right precedence; Looking at the core docs ( 
https://github.com/elm-lang/core/blob/master/src/Basics.elm ), (+) and (-) 
are 6, and (==), (/=), etc are 4.

On Friday, July 29, 2016 at 12:50:24 PM UTC-5, John Bugner wrote:
>
> I like the clever use of the (:::) function to make its function argument 
> (somewhat) look like a type.
>
> On Friday, July 29, 2016 at 11:48:26 AM UTC-5, Anton Lorenzen wrote:
>>
>> I just created a small library for this:
>> https://github.com/anfelor/elm-units
>>
>> It allows for time to be used like this:
>> Units.Time.every (30 ::: milliseconds) Tick
>>
>> Am Donnerstag, 28. Juli 2016 20:42:44 UTC+2 schrieb John Bugner:
>>>
>>> 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 28)` 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 

[elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-29 Thread John Bugner
I like the clever use of the (:::) function to make its function argument 
(somewhat) look like a type.

On Friday, July 29, 2016 at 11:48:26 AM UTC-5, Anton Lorenzen wrote:
>
> I just created a small library for this:
> https://github.com/anfelor/elm-units
>
> It allows for time to be used like this:
> Units.Time.every (30 ::: milliseconds) Tick
>
> Am Donnerstag, 28. Juli 2016 20:42:44 UTC+2 schrieb John Bugner:
>>
>> 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 28)` 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.

Re: [elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-29 Thread Duane Johnson
On Fri, Jul 29, 2016 at 10:48 AM, Anton Lorenzen  wrote:

> I just created a small library for this:
> https://github.com/anfelor/elm-units
>
> It allows for time to be used like this:
> Units.Time.every (30 ::: milliseconds) Tick
>


Neat! I'm surprised at what can be done with existing syntax and types.

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-29 Thread OvermindDL1
Yep, that is why I like the style that you can do with current code.  :-)

On Friday, July 29, 2016 at 6:35:46 AM UTC-6, John Bugner wrote:
>
> Also, thinking about this further, any definition of conversions between 
> types is probably best expressed as a function, because a conversion is not 
> always a simple multiple (like 1 yard = 3 feet). Take, for example, the 
> conversion between degrees celsius and degrees fahrenheit. (Note that if 
> `Temp` was a unit type, it's "base" unit should be Kelvin (or Rankine, I 
> suppose.), because Kelvin starts at 0, which lets multiplying temperatures 
> by a raw number make sense.)
>
> On Friday, July 29, 2016 at 7:11:19 AM UTC-5, John Bugner wrote:
>>
>> >This would be a nice fix to the Radians / Degrees issue too. Every 
>> language seems to settle on one or the other as "the base unit" but 
>> newcomers have to learn the assumption or face bad accidental outputs.
>> Yes, `degrees`, `radians`, and `turns` in `Basics` suffer the same 
>> problem.
>>
>> >F# is kind of radical in that it has units.
>> I didn't know this! (I have heard of F#, but I had never used or read 
>> some of its code.) It pleases me to know that I'm not the only one to think 
>> that is a problem, and that it can be solved by this solution! (F#'s 
>> implementation seems slightly different from what I am imagining, but close 
>> enough.)
>>
>> I'm curious though, does F# use its unit/measure types widely? or do 
>> common library functions (like those about time, angles, etc) still take a 
>> raw float type where it could take a unit/measure float type? How often do 
>> common 3rd-party libraries use this feature? How often do average-joe 
>> programmers use this feature?
>>
>> >Could possible do it 'now' with
>> >...
>> >If you do not expose the constructor of the type then it should be a 
>> fully opaque type, only able to be constructed via things like 
>> `milliseconds 500` or so.
>> As a work-around that uses only current features, I like this. It's an 
>> improvement over the current system of just having `Time` be an alias of 
>> `Float`. (Heck, `Angle` isn't even an alias! The angle functions' 
>> signatures are just `Float -> Float`!)
>>
>> On Thursday, July 28, 2016 at 3:13:27 PM UTC-5, OvermindDL1 wrote:
>>>
>>> Could possible do it 'now' with
>>>
>>> ```elm
>>> type Time
>>>   = Time_Value Float
>>>
>>> milliseconds m = seconds <| m/1000
>>>
>>> seconds s = Time_Value s
>>>
>>> minutes m = seconds <| m*60
>>>
>>> from_json json =
>>>   Json.Decode.decodeString Json.Decode.float json |> Result.map (\t -> 
>>> Time_Value t)
>>>
>>> to_seconds (Time_Value t) = t
>>>
>>> to_minutes t = 60 * (to_seconds t)
>>>
>>> to_json t = Json.Encode.float <| to_seconds t
>>> ```
>>>
>>> If you do not expose the constructor of the type then it should be a 
>>> fully opaque type, only able to be constructed via things like 
>>> `milliseconds 500` or so.
>>>
>>>
>>> On Thursday, July 28, 2016 at 12:42:44 PM UTC-6, John Bugner wrote:

 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 

[elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-29 Thread John Bugner
>This would be a nice fix to the Radians / Degrees issue too. Every 
language seems to settle on one or the other as "the base unit" but 
newcomers have to learn the assumption or face bad accidental outputs.
Yes, `degrees`, `radians`, and `turns` in `Basics` suffer the same problem.

>F# is kind of radical in that it has units.
I didn't know this! (I have heard of F#, but I had never used or read some 
of its code.) It pleases me to know that I'm not the only one to think that 
is a problem, and that it can be solved by this solution! (F#'s 
implementation seems slightly different from what I am imagining, but close 
enough.)

I'm curious though, does F# use its unit/measure types widely? or do common 
library functions (like those about time, angles, etc) still take a raw 
float type where it could take a unit/measure float type? How often do 
common 3rd-party libraries use this feature? How often do average-joe 
programmers use this feature?

>Could possible do it 'now' with
>...
>If you do not expose the constructor of the type then it should be a fully 
opaque type, only able to be constructed via things like `milliseconds 500` 
or so.
As a work-around that uses only current features, I like this. It's an 
improvement over the current system of just having `Time` be an alias of 
`Float`. (Heck, `Angle` isn't even an alias! The angle functions' 
signatures are just `Float -> Float`!)

On Thursday, July 28, 2016 at 3:13:27 PM UTC-5, OvermindDL1 wrote:
>
> Could possible do it 'now' with
>
> ```elm
> type Time
>   = Time_Value Float
>
> milliseconds m = seconds <| m/1000
>
> seconds s = Time_Value s
>
> minutes m = seconds <| m*60
>
> from_json json =
>   Json.Decode.decodeString Json.Decode.float json |> Result.map (\t -> 
> Time_Value t)
>
> to_seconds (Time_Value t) = t
>
> to_minutes t = 60 * (to_seconds t)
>
> to_json t = Json.Encode.float <| to_seconds t
> ```
>
> If you do not expose the constructor of the type then it should be a fully 
> opaque type, only able to be constructed via things like `milliseconds 500` 
> or so.
>
>
> On Thursday, July 28, 2016 at 12:42:44 PM UTC-6, John Bugner wrote:
>>
>> 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 

[elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-28 Thread OvermindDL1
Could possible do it 'now' with

```elm
type Time
  = Time_Value Float

milliseconds m = seconds <| m/1000

seconds s = Time_Value s

minutes m = seconds <| m*60

from_json json =
  Json.Decode.decodeString Json.Decode.float json |> Result.map (\t -> 
Time_Value t)

to_seconds (Time_Value t) = t

to_minutes t = 60 * (to_seconds t)

to_json t = Json.Encode.float <| to_seconds t
```

If you do not expose the constructor of the type then it should be a fully 
opaque type, only able to be constructed via things like `milliseconds 500` 
or so.


On Thursday, July 28, 2016 at 12:42:44 PM UTC-6, John Bugner wrote:
>
> 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 28)` 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 

Re: [elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-28 Thread Joey Eremondi
There is also some prior art with Haskell for this:

https://hackage.haskell.org/package/uom-plugin

https://hackage.haskell.org/package/units

https://hackage.haskell.org/package/Measure



On Thu, Jul 28, 2016 at 12:33 PM, Duane Johnson 
wrote:

>
> On Thu, Jul 28, 2016 at 1:11 PM, art yerkes  wrote:
>
>> F# is kind of radical in that it has units.
>>
>> https://fsharpforfunandprofit.com/posts/units-of-measure/
>>
>
> Wow, very neat! I like that F# keeps the units after the number, actually
> adding to readability.
>
> --
> 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 elm-discuss+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-28 Thread Duane Johnson
On Thu, Jul 28, 2016 at 1:11 PM, art yerkes  wrote:

> F# is kind of radical in that it has units.
>
> https://fsharpforfunandprofit.com/posts/units-of-measure/
>

Wow, very neat! I like that F# keeps the units after the number, actually
adding to readability.

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Unit Types : A Radical Proposal

2016-07-28 Thread art yerkes
F# is kind of radical in that it has units.

https://fsharpforfunandprofit.com/posts/units-of-measure/

It's not perfect, but it could serve as a starting point for evaluating 
different ways of having units as part of a language.

On Thursday, July 28, 2016 at 11:42:44 AM UTC-7, John Bugner wrote:
>
> 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 28)` 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.