Converting from m/s to km/h using F# Units of Measure

允我心安 提交于 2019-12-03 13:00:58

First, your msToKmph is totally incorrect. Although it returns a correct return value, what it is actually doing, is it just drops the original <m/s> value by converting to a plain, measureless float and then multiplies the measureless value to a 3.6<km/h>.

To better express the relations between UoM's, consider this:

let kmToM = 1000.0<m/km>  // relation between kilometers and meters
let hrToSec = 3600.0<s/h> // relation between seconds and hours
let msToKmph(speed : float<m/s>) =
    speed / kmToM * hrToSec

Note, all "magic numbers" are encapsulated within UoM converters, hence your formulas remain clean, e.g. they simply operate values and constants, but the UoM are calculated by the compiler.

Update: The philosophy of UoM conversion is that the conversion formulas should be something that has physical sense. The rule of thumb is whether your conversion value presents in reference books. In plain English, 3.6<km/h> from above is useless, but 1000.0<m/km> just says, "there is 1000 m in 1 km", which makes sense.

You can even improve hrToSec like this:

let hrToSec2 = 60.0<s/minute> * 60.0<minute/h>

This will make every value a well-known value found in reference books.

You're right that removing unit information is a bad thing. You should create a few constants with appropriate units for conversion.

let mPerKm = 1000.0<m/km>
let secondPerHour = 3600.0<s/h>

// val msToKmph : float<m/s> -> float<km/h>
let msToKmph(speed : float<m/s>) =
    speed / mPerKm * secondPerHour

For km and m, a generic solution is to define a unit prefix k so it works for many UoMs which have kilo as a metric:

[<Measure>] type k

let kilo = 1000.0<1/k>
let secondPerHour = 3600.0<s/h>

// val msToKmph : float<m/s> -> float<k m/h>
let msToKmph(speed : float<m/s>) =
    speed / kilo * secondPerHour
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!