2010-11-17 2 views
3

Les fonctions en ligne de F # avec les paramètres génériques résolus statiquement semblent être similaires aux modèles de C++. Cependant, contrairement au C++, vous devez spécifier les contraintes - comment cela fonctionne-t-il?Comprendre les paramètres de type F # en ligne et statiquement résolus: exemple de coulage F #

Par exemple, je suis en train de mettre en œuvre une fonction de transtypage ascendant, mais cela ne fonctionnera pas:

let inline myUpcast< ^a, ^b when ^a :> ^b > (x: ^a) : ^b = x 

Le message d'erreur est: erreur FS0698: contrainte non valide: le type utilisé pour la contrainte est scellée , ce qui signifie que la contrainte ne peut être satisfaite que par au plus une solution.

Je suis en fait d'essayer d'écrire une fonction qui jetteront des séquences lorsque les types sous-jacents peuvent être exprimés (pour contourner le manque de covariance), mais cette commande ne fonctionne pas tout à fait non plus:

let inline upcastseq (xs: seq<^a>) : seq<^b> when ^a :> ^b = xs :?> seq<^b> 

ce qui provoque l'avertissement suivant: warning FS0064: Cette construction provoque un code moins générique que celui indiqué par les annotations de type. La variable de type 'a a été contrainte à être de type'^b '. Comme on pouvait s'y attendre, l'utilisation de la fonction ne fonctionne pas comme prévu. Donc, je cherche une fonction qui provoquera une erreur de vérification de type si elle est utilisée pour convertir des séquences d'une manière covariante invalide (d'où la restriction de paramètre générique) - est-ce possible?

Un peu plus généralement, quelles sont les limites des paramètres de type à résolution statique par rapport aux modèles C++?

Répondre

3

Cela n'est pas possible, mais cela n'a aucun rapport avec les contraintes de membre statiques. En utilisant des contraintes génériques normales est également condamné, pour la même raison:

// doesn't work 
let myUpcast<'a, 'b when 'a :> 'b) (x: 'a) : 'b = unbox (box x) 

Fondamentalement F # ne permet pas de contraintes de type impliquant deux paramètres de type différents; ils sont toujours contraints d'être égaux.

Voir ma réponse à How to constrain one type parameter by another pour plus de commentaires.

+0

Ah, votre réponse liée répond assez exactement à mes besoins. Hélas ... –

+0

N'est-ce pas un peu bizarre que F # (dont l'inférence de type est censée être un argument de vente) ne puisse pas faire de telles contraintes de base, pourtant C# (et bien sûr le CLR) le supporte? Frustrant. –

+0

@Eamon - c'est très frustrant, mais je ne qualifierais pas ces contraintes de "basiques". Je suppose que moins de 5% des programmeurs C# utiliseront un paramètre de type contraint par un autre paramètre de type. – kvb