6
votes

Motif correspondant d'unités de mesure en f #

Cette fonction: xxx

produit une erreur

Le type 'float <' u> 'n'a pas de sous-types appropriés et ne peut pas être utilisé comme source d'un test de type ou d'une coercition d'exécution.

Y a-t-il une façon de moquer des unités de mesure de mesure?


0 commentaires

3 Réponses :


3
votes

Il y a deux problèmes avec votre approche. Tout d'abord, lorsque vous utilisez un soulignement dans la définition de votre fonction, c'est la même chose que d'utiliser une variable de type fraîche, votre définition est donc équivalente à ce qui suit: xxx

Quel message d'erreur vous dit que le compilateur savait que v est de type float <'u> et float <' u> n'a pas de sous-types appropriés , il ne sert donc pas à faire un test de type pour déterminer s'il s'agit d'un float ou de tout autre type.

Vous pouvez essayer de contourner cela par première boxe V dans un objet, puis effectuez un test de type. Cela fonctionnerait, par exemple, si vous aviez une liste <'a> et voulait voir s'il s'agissait d'une liste , car des informations complètes sur des objets génériques est suivi à l'heure d'exécution, y compris les paramètres de type générique (notamment, cela est différent de la manière dont d'autres accidents tels que le travail de Java). Malheureusement, les unités de mesure F # sont effacées au moment de l'exécution, cela ne fonctionnera donc pas ici - il n'existe aucun moyen que le système ne soit pas un moyen de déduire le type de mesure correct donnée à une représentation en boîte, car au moment de l'exécution, la valeur est juste un float clair - Système de F # pour les unités de mesure est en fait assez similaire à cet égard à la manière dont Java gère des types génériques génériques.

Afret, ce que vous essayez de faire semble être assez suspect - des fonctions qui sont des fonctions qui sont générique dans l'unité de mesure ne doit pas faire différentes choses en fonction de ce que le type de mesure est; ils devraient être correctement paramétriques. Qu'est-ce que vous essayez exactement d'atteindre? Cela ne ressemble certainement à une opération correspondant à la réalité physique, qui constitue la base des types de mesure de F #.


2 commentaires

Salut, merci pour la réponse. Je devrai repenser mon code une fois de plus. Un commentaire: Pourquoi une valeur avec des unités n'est pas simplifiée dans <1 / s> lors de l'utilisation de Microsoft.Fsharp.Math.si Module?


@Oldrich - ce n'est pas clair pour moi pourquoi ce n'est pas simplifié (ma lecture de la spécification indique qu'il devrait être), mais f # est conscient que ces mesures sont équivalentes (par exemple, vous pouvez écrire let (x: float <1 / s>) = 1.0 et le compilateur le permettra). Il est possible que des abréviations telles que PA ne soient pas toujours étendues à des fins d'affichage.



7
votes

comme @kvb explique en détail, le problème est que les unités de mesure font partie du type. Cela signifie que float est différent de type que float (et malheureusement, ces informations ne sont pas stockées dans le cadre de la valeur au moment de l'exécution).

Donc, vous essayez réellement d'écrire une fonction qui fonctionnerait avec deux types d'entrée différents. La solution fonctionnelle propre consiste à déclarer une union discriminée pouvant contenir des valeurs du premier type ou du second type: xxx

alors vous pouvez écrire la fonction à l'aide de la correspondance de modèle ordinaire: xxx

Vous devrez expliquer explicitement les valeurs dans la valeur de l'Union discriminée, mais c'est probablement le seul moyen de le faire directement (sans apporter de plus gros changements dans la structure du programme. ).

pour des types normaux tels que int et float , vous pouvez également utiliser des membres surchargés (déclarés dans certains types F #), mais ça ne Travaillez pour des parts de mesure, car la signature sera la même après que le compilateur F # efface les informations de l'unité.


0 commentaires

0
votes

Voir les unités à l'exécution section de http: //msdn.microsoft.com/en-us/library/dd233243.commexe .

Je suis d'accord avec @kvb, je pense que le meilleur moyen de contourner est de passer un objet.

Ce que je voudrais faire, en utilisant votre structure de code: xxx


0 commentaires