Методы расширения для конкретных универсальных типов
-
20-09-2019 - |
Вопрос
Я пытаюсь создать различные методы расширения для общего типа. привязан к конкретным параметрам универсального типа в F#, но этот язык, похоже, мне не позволяет:
Я хочу сделать что-то вроде следующего:
type IEnumerable<int> with
member this.foo =
this.ToString()
Тем не менее, это дает мне ошибку компилятора (подчеркивая int
ключевое слово):
Неожиданный идентификатор в имени типа.Ожидаемый инфиксный оператор, символ кавычки или другой токен.
Следующее делает работает, хотя он не привязывает конкретно параметр универсального типа к int
, как я хочу:
type IEnumerable<'a> with
member this.foo =
this.ToString()
Есть ли способ достичь этой цели в F # - возможно, я просто использую неправильный синтаксис?Если нет, я был бы признателен, если бы кто-нибудь предложил обходной путь, возможно, используя где-нибудь ограничения типа.
Решение
К сожалению, в текущей версии 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