8

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

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

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

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

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

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

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

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

ответ

7

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

+0

Кажется, вы действительно правы. Спасибо, в любом случае. – Noldorin

+0

Эта функция отслеживается предложением во внутренней базе данных ошибок F # «4548: методы поддержки расширения для конкретных экземпляров типа», но вряд ли это сделает сокращение для версии VS2010. – Brian

0

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

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

Хм ...

+1

Спасибо за предложение, но действительно, я работаю с закрытым типом здесь, поэтому он не совсем работает. – Noldorin

+0

Это, вероятно, не совсем то, что вы думаете ... Фактически вы определяете новый тип «IEnumerable» - попробуйте вызвать расширение на существующем «IEnumerable ». – kvb

6

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