Les méthodes d'Extension pour certains types génériques
-
20-09-2019 - |
Question
Je suis d'essayer de créer différentes méthode d'extension pour un type générique lié à certains paramètres de type générique en F#, mais la langue ne semble pas être de me permettre:
Ce que je veux faire, c'est quelque chose comme ce qui suit:
type IEnumerable<int> with
member this.foo =
this.ToString()
Pourtant, il me donne l'erreur du compilateur (en soulignant l' int
le mot-clé):
Inattendu identificateur de type de nom.Attendu opérateur infixe, devis symbole ou un autre jeton.
La suite n' travail, s'il ne doit pas se lier spécifiquement le paramètre de type générique pour int
, comme je veux:
type IEnumerable<'a> with
member this.foo =
this.ToString()
Est-il possible d'atteindre cet objectif dans F# je suis peut-être juste l'utilisation de la mauvaise syntaxe?Si non, je vous serais reconnaissant si quelqu'un pourrait proposer une solution de contournement, peut-être à l'aide de contraintes de type quelque part.
La solution
Ce n'est pas possible dans la version actuelle de F#, malheureusement.Voir la question relative à la ici.
Autres conseils
Générique des méthodes d'extension 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())
Eh bien, vous pouvez utiliser les contraintes, mais pas avec les scellés de type int.
type IEnumerable<'a when 'a :> InheritableType> =
member this.Blah =
this.ToString()
Hmm...
Afin d'aider les autres à la recherche pour des solutions similaires, voici un exemple montrant comment utiliser générique des méthodes d'extension avec des contraintes de type.Dans l'exemple ci-dessous, il y a une contrainte de type exigeant que le type de l'argument passé expose un constructeur par défaut.Ceci est fait en utilisant l' [<CLIMutable>]
attribut appliqué à la Order
record.Aussi, je suis constraing le résultat de la méthode pour le type passé.
Afin d'utiliser la méthode d'extension, vous devez spécifier le type que vous souhaitez utiliser.A noter que je suis aussi en train d'étendre un dictionnaire générique de l'interface.
[<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