Question

I have a function that converts from my own implementation of a 3D vector (which supports units of measure) to XNA's implementation:

type Vector3<[<Measure>]'a> with
    member inline v.ToXna() =
        Microsoft.Xna.Framework.Vector3(v.x / 1.f<_>, v.y / 1.f<_>, v.z / 1.f<_>)

When I compile it, I get a strange error:

The signature and implementation are not compatible because the type parameter in the class/signature has a different compile-time requirement to the one in the member/implementation

The inline seems to be a necessity; without it, I get this error:

This construct causes code to be less generic than indicated by the type annotations. The unit-of-measure variable 'a has been constrained to be measure 'm'.

Any idea what's going on?

Edit To answer @svick's questions, Vector3 is defined as:

type Vector3<[<Measure>]'u> =
    struct
        val x:float32<'u>
        val y:float32<'u>
        val z:float32<'u>
        new(x, y, z) = { x = x; y = y; z = z }
    end

And I'm also having some type inference problems defining it as a normal function:

let vector3 (v:DumpEngine.Vector3<_>) =
    Vector3(v.x / 1.f<_>, v.y / 1.f<_>, v.z / 1.f<_>)

Causes the function to be a Vector3<1> -> Microsoft.Xna.Framework.Vector3, which makes it quite unusable. I'm not sure this is a related issue, though.

Was it helpful?

Solution

I have no idea what's going on, but this seems to work:

let inline ToXna(v:Vector3<'a>) =
    Microsoft.Xna.Framework.Vector3(v.x / 1.f<_>, v.y / 1.f<_>, v.z / 1.f<_>)

It's the best I managed to do, though.

OTHER TIPS

Another solution, which circumvents the problem entirely by using a cast rather than a divison:

type Vector3<[<Measure>]'u> with
    member inline v.ToXna() =
        Microsoft.Xna.Framework.Vector3(float32 v.x, float32 v.y, float32 v.z)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top