1

Assume such measures are defined:

[<Measure>] type kilogram
[<Measure>] type kg = kilogram

[<Measure>] type s

When I define a binding like this:

let x = 1.<kg / kilogram> // Type of x: float

F# correctly simplifies type of x from float<kg/kilogram> to float. But when I add another unit like this:

let y = 1.<kg s / kilogram> // Type of y: float<kg s / kilogram>

Instead of simplfying type of y to float<s>, it shows float<kg s / kilogram>

Why doesn't F# simplify it in this case? Am I doing something wrong?

Avestura
  • 1,438
  • 14
  • 24

1 Answers1

2

As far as I can see based on a couple of experiments, the only place where the compiler uses the fact that kg = kilogram in the simplification process is when the final type is unit-less, i.e. float<1> type. In all other cases I tried, it keeps both kg and kilogram in the unit type.

I suspect the compiler still knows that the type of 1.<kg/kilogram> is kg/kilogram, but because this is equivalent to 1, it does not display it - it shows float rather than float<1> or float<kg/kilogram>.

It is worht noting that the simplificiation happens when it is actually needed - if you try comparing a value 1.<kg s / kilogram> with a value 1.<s / 1>, this is well-typed:

let y = 1.<kg s / kilogram>
y = 1.<s/1>

I do not have a solid evidence (like a link to the specification), but I think the compiler only does the simplification when it actually has to, but otherwise keeps the unit annotations as you write them.

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • 2
    This is consistent with other mechanisms that let you create equivalent types, like type abbreviations. If you define `type MyType = string` and then write `let x : MyType = "hello"` it will (intuitively) annotate the type as MyType, pretty much because _that's what you told it to do_. This goes further of course – Jwosty Jul 01 '19 at 22:35