2 votes

Définir les plages de valeurs autorisées dans le type member en F#

Je joue avec unités de mesure en F# et j'essaie actuellement de créer des unités de mesure composées pour la longueur et la masse afin de refléter le langage familier dans le système impérial, par exemple "Je mesure 1,5 m 10" ou "Elle pèse 2,5 kg" aux États-Unis et au Royaume-Uni.

J'ai défini un module pour les unités standard (non composées) comme suit :

module Units
    // Mass
    [<Measure>] type kg // Kilogram
    [<Measure>] type g  // Gram
    [<Measure>] type lb // Pound (mass)
    [<Measure>] type st // Stone (mass)

    // Conversions
    ...

    // Length
    [<Measure>] type m      // Metre
    [<Measure>] type cm     // Centimetre
    [<Measure>] type inch   // Inch
    [<Measure>] type ft     // Foot

    // Conversions
    ...

Et j'ai défini les unités composées dans un autre module :

module CompoundUnits
    open Units

    // Mass
    type StonesAndPounds = {
        Stones: float<st>
        Pounds: float<lb>
    }

    // Length
    type FeetAndInches = {
        Feet: float<ft>
        Inches: float<inch>
    }

Cependant, avec la manière dont j'ai actuellement écrit les types de masse et de longueur composées, il y a de la place pour des états illégaux (tels que des valeurs négatives) et des états qui sont techniquement correct mais pas de préférence :

// 39 lbs = 2 st 11 lbs
let eightStoneEleven: StonesAndPounds = { Stones = 6.0<st>; Pounds = 39.0<lb> }
// 22" = 1' 10"
let fiveFootTen: FeetAndInches = { Feet = 4.0<ft>; Inches = 22.0<inch> }

Dans son livre "Domain Modeling made Functional", Scott Wlaschin parle de rendre les états illégaux non représentables. Je me demandais donc s'il existait un moyen d'appliquer une sorte de restriction sur mes types composés afin que 0<ft> <= Feet , 0<inch> <= Inches <= 12<inch> y 0<st> <= Stones , 0<lb> <= Pounds <= 14<lb> .

0voto

Ryan Points 1153

Un modèle commun est de créer un module pour le type, qui contient sa définition plus create et d'autres fonctions de validation.

Scott propose quelques exemples sur son site Web, dans le cadre de sa série "Designing with Types".

https://fsharpforfunandprofit.com/posts/designing-with-types-non-strings/

Vous ne pouvez pas appliquer les restrictions sur les unités de mesure elles-mêmes, mais vous pouvez créer des types dédiés pour représenter vos mesures composées comme le fait Scott avec SafeDate y NonNegativeInt etc.

Ceux-ci pourraient toujours utiliser les unités de mesure "standard" pour les propriétés de leurs composants.

Une citation de l'article :

"Les unités de mesure peuvent en effet être utilisées pour éviter de mélanger des valeurs numériques de type différent, et sont beaucoup plus puissantes que les unions à cas unique que nous utilisions jusqu'à présent.

En revanche, les unités de mesure ne sont pas encapsulées et ne peuvent pas avoir de contraintes. N'importe qui peut créer un int avec l'unité de mesure say, et il n'y a pas de valeur min ou max. "

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X