let’s say I’ve defined an F# module for handling 3-dimensional vectors and measure unit:
[<Measure>]
type m
[<Measure>]
type s
[<Measure>]
type v = m/s
[<Measure>]
type rad
type Vector3<[<Measure>] 'a> =
{
X : float<'a>
Y : float<'a>
Z : float<'a>
}
And somewhere I have an angle expressed in radians:
let angle:float32<rad> = 0.5f<rad>
Now I have to declare a Vector3 (velocity) using the angle to calculate its components. I tried something like :
let velocity : Vector3<m/s> = { X = Math.Cos(angle);Y = Math.Sin(angle);Z = 0.0<m/s>} //don't compile
The code above doesn’t compile because Vector3 is expecting a value in X and Y but Sin returns a float.
How can I solve this problem? If it possible I would like to perform a conversion between measure units, instead of a cast, in such a way that the compiler can guarantee that I’m doing the right thing while transforming an angle into a velocity.
Any suggestion?
Several problems here:
cosis expecting a unitless value, so you have to take the units offangle; given that velocity is expectingfloatand notfloat32, you might as well just convert directly tofloat(which removes the units).Then, you need to put the units back on. In first versions of units of measure, you could do this by simply multiplying by 1 in the appropriate measure. Now there is
LanguagePrimitives.FloatWithMeasure, which is more correct, but slightly more verbose.That aside, 10 radians is a funny angle…
(Note that
cosandsinare built-in)