Методы расширения для конкретных универсальных типов


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

Я хочу сделать примерно следующее:

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

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

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

Работает следующее , хотя он специально не привязывает параметр generic type к int, как я хочу:

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

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

4 8

4 ответа:

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

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

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

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

Хм...

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