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

Aar*_*ach 6 generics f# units-of-measurement .net-4.6

在定义具有参数的运算符时,我遇到了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))  
Run Code Online (Sandbox Code Playgroud)

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

我想将此用于类型转换,其中十进制数是不可能的.我的目标是创建用于处理Quotients的运算符,而不是将逻辑用于计算每个类型转换中的余数.是否有可能实现这一目标,还是应该以不同的方式进行类型转换?

The*_*ght 10

有趣的问题.如果您取出'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>
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为任何剩余部分都是原始单位.

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)
Run Code Online (Sandbox Code Playgroud)