F# 为受约束的泛型参数创建实例方法

F# create instance method for a constrained generic parameter

是否可以有一个 class 的实例方法,它只在泛型类型被限制为特定类型时才有效?

例如,我想定义一个 Add 方法,该方法仅在包含的类型为 float 时有效。这是我得到的最接近的,但我不确定如何在成员 _.Add 签名中将 'Value 类型限制为 float。现在我在最后一行的旁边收到一条错误消息,说 'Value 的类型无法在编译时解析。我可以限制此方法仅在 'Value 的类型为 float 时应用吗?

type ImArr<[<Measure>] 'Index, 'Value>(values: array<'Value>) =
    // We want to make sure we have our own copy to protect against mutation
    let values = values |> Array.copy

    member internal _.Values : array<'Value> = values

    member this.Item
        with get(index: int<'Index>) =
            values.[int index]


type Arr<[<Measure>] 'Index, 'Value>(values: array<'Value>) =
    // We want to make sure we have our own copy to protect against mutation
    let values = values |> Array.copy

    member this.Item
        with get(index: int<'Index>) =
            values.[int index]

        and set(index: int<'Index>) (value: 'Value) =
            values.[int index] <- value

    member internal _.Values : array<'Value> = values

    // This is the method I would like to constrain to only be used when the
    // type of 'Value is float
    member _.Add (b: ImArr<'Index, float>) =
        if values.Length <> b.Values.Length then
            invalidArg (nameof b) "Cannot add arrays of different lengths"
        // TODO: Turn this into something using SIMD intrinsics
        let mutable i = 0
        while i < values.Length && i < b.Values.Length do
            values.[i] <- values.[i] + b.Values.[i] // <-- Error here
            i <- i + 1

正如@brianberns 在评论中提到的,不是直接提到的。但是,可以为 class 的特殊版本定义 C#-style extension methods。需要注意的是,作为扩展方法,它无法访问私有成员。

[<Extension>]
type ArrExtensions =

    [<Extension>]
    static member Add (this: ImArr<'Index, float>, b: ImArr<'Index, float>) =
        if this.Values.Length <> b.Values.Length then
            invalidArg (nameof b) "Cannot add arrays of different lengths"
        // TODO: Turn this into something using SIMD intrinsics
        let mutable i = 0
        while i < this.Values.Length && i < b.Values.Length do
            this.Values.[i] <- this.Values.[i] + b.Values.[i] // <-- Error here
            i <- i + 1

// When the namespace containing the above type is opened,
// the following can be called:

floatArr1.Add(floatArr2)