首页 > 解决方案 > F# 为受约束的泛型参数创建实例方法

问题描述

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

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

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

标签: f#

解决方案


正如@brianberns 在评论中提到的,不是直接的。但是,可以为类的专用版本定义C# 样式的扩展方法。需要注意的是,作为一种扩展方法,它不能访问私有成员。

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

推荐阅读