Странная ошибка и другое странное поведение с общей структурой единиц измерения в F # - PullRequest
0 голосов
/ 29 августа 2011

У меня есть такой тип:

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 ]

4 голосов
/ 29 августа 2011

В другом месте вашего кода должно быть что-то не так.Если вы сбросите F # Interactive, откроете новый пустой файл F # Script и вставите следующий код (а затем запустите его в 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 голос
/ 29 августа 2011

Вам необходимо указать атрибут Значение по умолчанию для полей 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> }

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