10

我正在尝试为绑定到F# 中特定泛型类型参数的泛型类型创建各种扩展方法,但该语言似乎不允许我:

我想做的是如下所示:

type IEnumerable<int> with
    member this.foo =
        this.ToString()

然而它给了我编译器错误(在int关键字下划线):

类型名称中有意外的标识符。预期的中缀运算符、引号符号或其他标记。

以下确实有效,尽管它没有int像我想要的那样专门将泛型类型参数绑定到:

type IEnumerable<'a> with
    member this.foo =
        this.ToString()

有什么方法可以在 F# 中实现这一目标 - 我可能只是使用了错误的语法吗?如果没有,如果有人可以提出解决方法,我将不胜感激,也许在某处使用类型约束。

4

4 回答 4

9

现在 F# 3.1 中提供了通用扩展方法:

open System.Runtime.CompilerServices
open System.Collections.Generic

[<Extension>]
type Utils () =
    [<Extension>]
    static member inline Abc(obj: IEnumerable<int>) = obj.ToString()

printfn "%A" ([1..10].Abc())
于 2014-04-22T00:54:32.133 回答
8

不幸的是,这在当前版本的 F# 中是不可能的。在此处查看相关问题。

于 2009-10-07T13:51:59.057 回答
0

好吧,你可以使用约束——但不能使用像 int 这样的密封类型。

type IEnumerable<'a when 'a :> InheritableType> =
member this.Blah =
    this.ToString()

唔...

于 2009-10-07T13:31:11.590 回答
0

为了帮助其他人寻找类似的解决方案,这里有一个示例,展示了如何使用具有类型约束的泛型扩展方法。在下面的示例中,有一个类型约束要求传递的类型参数公开一个默认构造函数。这是使用[<CLIMutable>]应用于Order记录的属性来完成的。另外,我将方法的结果限制为传递的类型。

为了使用扩展方法,您必须指定要使用的类型。请注意,我还在扩展通用字典接口。

[<Extension>]
type ExtensionMethds () = 

    [<Extension>]
    static member inline toObject<'T when 'T: (new: unit -> 'T)> (dic: IDictionary<string,obj>): 'T =
        let instance = new 'T()
        // todo: set properties via reflection using the dictionary passed in
        instance


[<CLIMutable>]
type Order = {id: int}

let usage = 
    let dictionaryWithDataFromDb = dict ["id","1" :> obj] 
    let theOrder = dictionaryWithDataFromDb.toObject<Order>()
    theOrder
于 2016-07-17T01:30:52.757 回答