F#中通用计量单位结构的奇怪错误和其他奇怪行为

时间:2011-08-29 09:42:34

标签: f# units-of-measurement

我有这种类型:

type Vector3<[<Measure>]'u> =
    struct
        val x:float32<'u>
        val y:float32<'u>
        val z:float32<'u>
    end

    new(x, y, z) = { x = x; y = y; z = z }

当我尝试制作默认实例时,它会给我一个奇怪的错误,我在Google上找不到任何有关的信息:

  

错误5只有在结构类型的所有字段都允许默认初始化时才可以使用结构类型的默认零初始化构造函数

好吧,我可以使用默认构造函数将所有内容设置为0。或者不是。

let f = Vector3(0.f<N>, 0.f<N>, 0.f<N>)

给我一​​个错误:

  

错误1此表达式的类型为float32,但此处的类型为float32

当我在后续计算中使用此实例时,似乎只会发生这种情况;否则,它会正确地将f的类型解析为Vector3<N>。给构造函数赋予类型,如Vector3<N>(...)似乎也解决了问题,这真的很奇怪。

我有什么问题吗?

2 个答案:

答案 0 :(得分:4)

代码中的其他地方一定有问题。如果重置F#Interactive,打开一个新的空F#脚本文件并粘贴以下代码(然后在FSI中运行),那么一切正常对我来说:

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

[<Measure>] type N    
let f = Vector3(0.f<N>, 0.f<N>, 0.f<N>) 

我建议使用隐式构造函数语法编写代码,这种语法更简洁,更加惯用F#(struct .. end声明仍然允许,但它主要用于旧版本的F#)。默认构造函数似乎在这种情况下不起作用,但您可以使用静态成员:

[<Struct>]
type Vector3<[<Measure>]'u>(x:float32<'u>, y:float32<'u>, z:float32<'u>) =
    member this.X = x    
    member this.Y = y
    member this.Z = z
    static member Empty : Vector3<'u> = Vector3(0.f<_>, 0.f<_>, 0.f<_>)

[<Measure>] type N

let f1 = Vector3<N>.Empty
let f2 = Vector3(0.f<N>, 0.f<N>, 0.f<N>) 
f1.X + f2.X

答案 1 :(得分:1)

您需要为val字段指定默认值属性:

type Vector3<[<Measure>]'u> =
    struct
        [<DefaultValue(false)>] val mutable x:float32<'u>
        [<DefaultValue(false)>] val mutable y:float32<'u>
        [<DefaultValue(false)>] val mutable z:float32<'u>
    end
    member X.Init(x,y,z) = 
        X.x <- x
        X.y <- y
        X.z <- z

或使用记录类型:

type Vector3<[<Measure>]'u> = { x : float32<'u>; y : float32<'u> ; z : float32<'u> }
[<Measure>] type N
let v = { x = 10.0F<N>; y = 10.0F<N>; z = 10.0F<N> }

<强>更新

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