Search code examples
f#units-of-measurementsimplification

F# Units of Measure doesn't simplify


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?


Solution

  • 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.