Методы расширения для определенных универсальных типов - PullRequest
9 голосов
/ 07 октября 2009

Я пытаюсь создать различные методы расширения для универсального типа , привязанного к конкретным параметрам универсального типа в F #, но язык, похоже, не позволяет мне:

Я хочу сделать что-то вроде следующего:

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

Тем не менее, это дает мне ошибку компилятора (подчеркивая ключевое слово int):

Неожиданный идентификатор в имени типа. Ожидаемый инфиксный оператор, символ кавычки или другой токен.

Следующая работает , хотя и не привязывает параметр общего типа к int, как я хочу:

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

Есть ли способ достичь этой цели в F # - возможно, я просто использую неправильный синтаксис? Если нет, я был бы признателен, если бы кто-то мог предложить обходной путь, возможно, где-нибудь использовать ограничения типов.

Ответы [ 4 ]

8 голосов
/ 22 апреля 2014

Общие методы расширения теперь доступны в 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())
7 голосов
/ 07 октября 2009

К сожалению, в текущей версии F # это невозможно. См. Связанный вопрос здесь .

0 голосов
/ 17 июля 2016

Чтобы помочь другим, ищущим похожие решения, вот пример, показывающий, как использовать универсальные методы расширения с ограничениями типов. В приведенном ниже примере есть ограничение типа, требующее, чтобы переданный аргумент типа предоставил конструктор по умолчанию. Это делается с помощью атрибута [<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
0 голосов
/ 07 октября 2009

Ну, вы можете использовать ограничения - но не с закрытыми типами, такими как int.

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

Хм ...

...