Методы расширения для конкретных универсальных типов
Я пытаюсь создать различные методы расширения для универсального типа , привязанного к определенным параметрам универсального типа В 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 ответа:
К сожалению, в текущей версии 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