参数中的 F# 通用单元相互定义

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

我在定义一个运算符时遇到了 F# 度量单位的问题,该运算符的参数具有根据另一个参数的通用度量单位定义的通用度量单位。例如:

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

这里,y定义在<'a/'b>,其中<'a>x的单位。我期望 (|/) 的类型是 int64<'a> -> int64<'a/'b> -> Quotient<'b>,但是编译器告诉我类型是 x:int64<'b> -> y:int64 -> Quotient<'b>.

我想将其用于无法使用十进制数字的类型转换。我的目标是创建用于处理商的运算符,而不是在每个类型转换中放入计算余数的逻辑。是否有可能实现这个目标,或者我应该以不同的方式进行类型转换?

有趣的问题。如果你取出 'a/'b 并用 'b 替换它,你会看到编译器突然在 - 运算符上给你一个警告。

它告诉你减法的左右单位必须相同,因此它已将 'b 限制为 1 的度量。为什么?

x 的单位是 'a

q 的单位是 'b

这告诉您实际上您的商需要两个度量参数。

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

这是有道理的,因为任何余数都将以原始单位表示。

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)