2016-03-11 2 views
6

У меня возникают проблемы с единицами измерения F # при определении оператора, который имеет параметр с общей единицей измерения, определенной в терминах общей единицы измерения из другого параметра. Например: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>.

Я хочу использовать это для преобразования типов, где десятичные числа невозможны. Моя цель состояла в том, чтобы создать операторов для работы с Quotients вместо того, чтобы поместить логику для вычисления остатка в каждом преобразовании типа. Возможно ли достичь этой цели, или я должен идти о моих преобразованиях по-другому?

ответ

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> 

Это имеет смысл, поскольку любой остаток будет находиться в исходных единицах.

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) 
Смежные вопросы