如何为泛型类型编写扩展方法,其中一个类型变量必须是字符串?

How to write an extension method for a generic type, where one type variable has to be string?

特别想为这个类型写一个扩展方法:

type Frame<'TRowKey, string when 'TRowKey : equality> with
  member frame.someMethod =
    // code

使用该代码,我收到此错误:

Unexpected identifier in type name. Expected infix operator, quote symbol or other token.

String 替换 string 得到相同的结果。

原始类型是来自 Deedle 库的 Frame<'TRowKey, 'TColumnKey (requires equality and equality)>

我没有 Deedle 来测试这段代码,但你应该使用 .NET 扩展方法:

open System

[<Runtime.CompilerServices.Extension>]
module Extensions =
    [<Runtime.CompilerServices.Extension>]
    let someMethod<'TRowKey when 'TRowKey : equality> (frame :Frame<'TRowKey, string>) = // body

这与 scrwtp 调用 'the idiomatic way' 的方式相同(我不喜欢讨论同质性)但同时它可以作为扩展方法从 C# 运行。

如果您想从 F# 中使用它以及扩展,则必须将其声明为类型:

[<Runtime.CompilerServices.Extension>]
type Extensions =
    [<Runtime.CompilerServices.Extension>]
    static member someMethod<'TRowKey when 'TRowKey : equality> (frame :Frame<'TRowKey, string>) = // body

所以现在您可以键入 row.,如果第二个参数是字符串,intellisense 只会显示扩展名。

@Gustavo 对如何使用扩展方法进行了详尽的解答。但是,如果您没有特别充分的理由认为这是一种扩展方法(如 C# 互操作),您可能只使用一个简单的函数:

type Frame<'row, 'col> = { row: 'row; col: 'col }

module Frame = 
    let restricted (frame: Frame<'row, string>) = frame

Frame.restricted { row = 3; col = "test" } // compiles
Frame.restricted { row = 3; col = 5 }      // doesn't

这就是我在编写纯 F# 代码时考虑的一种更简洁的方法 - 当绑定函数作为类型的固有部分没有意义时比方法更可取,并且属性的干扰更少。