2016-03-11 2 views
6

J'ai des problèmes avec les unités de mesure F # lorsque je définis un opérateur qui a un paramètre avec une unité générique de mesure définie en termes d'unité de mesure générique d'un autre paramètre. Par exemple:F # unités génériques dans les paramètres définis les uns par rapport aux autres

type Quotient<[<Measure>]'b> = 
| Divisible of int64<'b> 
| Remaindered of int64<'b> * int64<'b> 

let (|/) (x: int64<'a>) (y: int64<'a/'b>) = 
    let q = x/y 
    if q * y = x then Divisible q else Remaindered (q, x - (q * y)) 

Ici, y est défini dans <'a/'b>, où <'a> est l'unité de x. Je m'attends à ce que le type de (|/) soit int64<'a> -> int64<'a/'b> -> Quotient<'b>, mais le compilateur me dit que le type est x:int64<'b> -> y:int64 -> Quotient<'b>.

Je veux utiliser ceci pour les conversions de type où les nombres décimaux ne sont pas possibles. Mon but était de créer des opérateurs pour travailler avec Quotients au lieu de mettre la logique pour calculer le reste dans chaque conversion de type. Est-il possible d'atteindre cet objectif, ou devrais-je procéder différemment à mes conversions de type?

Répondre

10

Question intéressante. Si vous enlevez le 'a/'b et le remplacez par 'b, vous verrez que le compilateur vous donne soudainement un avertissement sur l'opérateur -. Il est dit que les unités à gauche et à droite de la soustraction doivent être les mêmes, donc il a été contraint 'b d'être de 1 de mesure

Pourquoi?

x a des unités de 'a

q a des unités de 'b

Cela vous indique que vous avez besoin en fait deux paramètres de mesure pour votre quotient.

type Quotient<[<Measure>]'a, [<Measure>]'b> = 
    |Divisible of int64<'a> 
    |Remaindered of int64<'a> * int64<'b> 

Ceci est logique car tout reste serait dans les unités d'origine.

let (|/) (x: int64<'a>) (y: int64<'a/'b>) : Quotient<'b,'a> = 
    let q = x/y 
    if q * y = x then Divisible q else Remaindered (q, x - q * y)