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

I am having problems with F # units when defining an operator that has a parameter with a common unit of measure defined in terms of a common unit of measure from another parameter. For instance:

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 defined in <'a/'b> , where <'a> is the unit of x . I expect the type (|/) be int64<'a> -> int64<'a/'b> -> Quotient<'b> , however the compiler tells me that type x:int64<'b> -> y:int64 -> Quotient<'b> .

I want to use this for type conversion where decimal numbers are not possible. My goal was to create operators to work with Quotients instead of putting logic to calculate the remainder in each type conversion. Is it possible to achieve this goal, or should I go about my transformations differently?

+6
source share
1 answer

Interest Ask. If you pull out 'a/'b and replace it with 'b , you will see that the compiler unexpectedly gives you a warning in the - statement.

This tells you that the units to the left and right of the subtraction should be the same, so he limited 'b measure 1 . Why?

x has units 'a

q has units 'b

This tells you that you really need two measurement parameters for your quotient.

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

This makes sense because any remainder will 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) 
+10
source

All Articles