8

je tente de créer diverses méthodes d'extension pour un type générique lié aux paramètres de type générique spécifiques en F #, mais la langue ne semble pas être me permettre:Les méthodes d'extension pour les types génériques spécifiques

Ce que je veulent faire quelque chose comme ce qui suit:

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

Pourtant, il me donne l'erreur du compilateur (soulignant le mot-clé int):

Identificateur inattendu dans le nom du type. Opérateur infixe attendu, symbole de citation ou autre jeton.

Ce qui suit ne travail, même si elle ne se lie pas spécifiquement le paramètre de type générique à int, comme je veux:

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

Est-il possible d'atteindre cet objectif en F # - suis-je peut-être juste en utilisant la mauvaise syntaxe? Sinon, j'apprécierais que quelqu'un propose une solution de contournement, en utilisant peut-être des contraintes de type quelque part.

Répondre

7

Ce n'est pas possible dans la version actuelle de F #, malheureusement. Voir la question connexe here.

+0

Vous semblez correct. Merci quand même. – Noldorin

+0

Cette fonctionnalité est suivie par une suggestion dans la base de données de bogues interne F # "4548: Prise en charge des méthodes d'extension pour des instanciations de type spécifiques", mais il est peu probable qu'elle soit utilisée pour la version VS2010. – Brian

0

Eh bien, vous pouvez utiliser des contraintes - mais pas avec des types scellés comme int.

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

Hmm ...

+1

Merci pour la suggestion, mais en effet, je travaille avec un type scellé ici, donc ça ne marche pas tout à fait. – Noldorin

+0

Cela ne fait probablement pas ce que vous pensez ... Vous définissez en fait un nouveau type 'IEnumerable' - essayez d'appeler l'extension sur un' IEnumerable 'existant. – kvb

6

méthodes d'extension génériques sont maintenant disponibles en 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

Afin d'aider les autres à la recherche de solutions similaires, voici un exemple montrant comment utiliser des méthodes d'extension génériques avec des contraintes de type. Dans l'exemple ci-dessous, il existe une contrainte de type exigeant que l'argument type passé expose un constructeur par défaut. Ceci est fait en utilisant l'attribut [<CLIMutable>] appliqué à l'enregistrement Order. Aussi, je constraing le résultat de la méthode au type passé.

Pour utiliser la méthode d'extension, vous devez spécifier le type que vous souhaitez utiliser. Notez que j'étends également une interface de dictionnaire générique.

[<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 
Questions connexes