简体   繁体   中英

F# generic units in parameters defined in terms of each other

I am having trouble with F# Units of Measure when defining an operator that has a parameter with a generic unit of measure defined in terms of the generic unit of measure from another parameter. For example:

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

Here, y is defined in <'a/'b> , where <'a> is the unit of x . I am expecting the type of (|/) to be int64<'a> -> int64<'a/'b> -> Quotient<'b> , however the compiler is telling me the type is x:int64<'b> -> y:int64 -> Quotient<'b> .

I want to use this for type conversions where decimal numbers are not possible. My goal was to create operators for working with Quotients instead of putting the logic to compute the remainder in every type conversion. Is it possible to achieve this goal, or should I go about my type conversions a different way?

Interesting question. If you take out the 'a/'b and replace it with 'b , you'll see that the compiler suddenly gives you a warning on the - operator.

It's telling you that the units on the left and right of the subtraction have to be the same so it has constrained 'b to be of measure 1 . Why?

x has units of 'a

q has units of 'b

This tells you that you actually need two measure parameters for your quotient.

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

This make sense because any remainder would be in the original units.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM