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

发布于 2024-12-01 15:47:42 字数 780 浏览 3 评论 0原文

我有这种类型:

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。为构造函数提供类型,如 Vector3(...) 似乎也解决了问题,这确实很奇怪。

我做错了什么吗?

I have this type:

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 }

When I try to make a default instance, it gives me a strange error that I couldn't find any information on Google about:

Error 5 The default, zero-initializing constructor of a struct type may only be used if all the fields of the struct type admit default initialization

So okay, I can just use the default constructor to set everything to 0 with. Or not.

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

Gives me an error:

Error 1 This expression was expected to have type float32 but here has type float32

This only seems to happen when I use this instance in a subsequent calculation; otherwise, it correctly resolves the type of f as being Vector3<N>. Giving the constructor the type, as in Vector3<N>(...) seems to also solve the problem, which is really strange.

Is there something I'm doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

万劫不复 2024-12-08 15:47:42

您的代码中的其他地方一定有问题。如果您重置 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

There must be something wrong elsewhere in your code. If you reset F# Interactive, open a new empty F# Script file and paste the following code (and then run it in FSI), then everything works just fine for me:

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>) 

I would recommend writing the code using implicit constructor syntax which is more succinct and more idiomatic F# (the struct .. end declaration is still allowed, but it has been used mainly in old versions of F#). Default constructor doesn't seem to work in this scenario, but you can use static member:

[<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
幸福%小乖 2024-12-08 15:47:42

您需要为 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

You need to specify the Default Value attribute for val fields:

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

Or use record types:

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> }

UPDATE:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文