2016-03-11 30 views
6

Ho problemi con le unità di misura F # quando si definisce un operatore che ha un parametro con un'unità di misura generica definita in termini di unità di misura generica da un altro parametro. Ad esempio:Unità generiche F # in parametri definiti in termini reciproci

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)) 

Qui, y è definita <'a/'b>, dove <'a> è l'unità di x. Mi aspetto che il tipo di (|/) sia int64<'a> -> int64<'a/'b> -> Quotient<'b>, tuttavia il compilatore mi sta dicendo che il tipo è x:int64<'b> -> y:int64 -> Quotient<'b>.

Voglio utilizzare questo per le conversioni di tipi in cui i numeri decimali non sono possibili. Il mio obiettivo era creare operatori per lavorare con Quotients invece di mettere la logica per calcolare il resto in ogni conversione di tipo. È possibile raggiungere questo obiettivo, o dovrei parlare del mio tipo di conversioni in un modo diverso?

risposta

10

Interessante domanda. Se si estrae lo 'a/'b e lo si sostituisce con 'b, si noterà che il compilatore improvvisamente emette un avviso sull'operatore -.

Si sta dicendo che le unità a sinistra e a destra della sottrazione devono essere le stesse in modo da limitare 'b ad essere di misura 1. Perché?

x ha unità di 'a

q ha unità di 'b

Questo ti dice che in realtà bisogno di due parametri di misura per il vostro quoziente.

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

Questo ha senso perché ogni resto sarebbe nelle unità originali.

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)