int64 не поддерживает LanguagePrimitives.DivideByInt? - PullRequest
2 голосов
/ 02 марта 2012

Почему int64 не поддерживает LanguagePrimitives.DivideByInt? Я думал, что было бы вполне естественно написать что-то вроде этого:

let inline DivBy2 n = LanguagePrimitives.DivideByInt n 2
let res = DivBy2 100L

Но компилятор говорит, что int64 doesn't support the operator DivideByInt.

Я пытался обмануть:

type System.Int64 with 
    static member DivideByInt (n: System.Int64) (d: int) = n / (int64 d)

Но это не работает.

Что можно сделать, чтобы выполнить общее деление int64 на int?

Ответы [ 5 ]

6 голосов
/ 02 марта 2012

Глядя на исходный код F #, тип int64 не включен в функцию DivideByInt, я не знаю почему.

Вы можете определить другую обобщенную функцию, например:

open LanguagePrimitives
type DivExtension = DivExtension of int with
    static member inline (=>) (x             , DivExtension y) = DivideByInt x y
    static member        (=>) (x:int64       , DivExtension y) = x / (int64 y)
    static member        (=>) (x:DivExtension, DivExtension y) = x

let inline DivByInt x y = x => DivExtension y

Или вы можете даже затенить оригинальную функцию DivideByInt:

let inline DivideByInt x y = x => DivExtension y

Обратите внимание, что вы также можете добавить больше перегрузок (например, для int), в этом случае вам не нужен последний "манекен""перегрузка, чтобы вывести правильную подпись.

2 голосов
/ 08 марта 2012

Я получил ответ от Дона Сайма (по электронной почте от fsbugs), когда я спросил об отсутствии MutliplyByInt и ограниченной поддержке DivideByInt:

Дон отвечает:

Этот оператор существует для поддержки «Seq.averageBy» и т. Д. Он представляет собой псевдоточное деление суммы на счет. Мы не расширили механизм за пределы того, что было необходимо для этого.

Похоже, я неправильно понял цель этого механизма. Но я до сих пор не знаю, почему нет поддержки int64 для DivideByInt, это означает, что мы ограничены в общих операциях для типа int64. Возможно, я запутался, потому что int64 выглядит как примитивный тип, когда это не примитивный тип. И DivideByInt определен только для примитивных типов, поэтому его не поддерживают.

1 голос
/ 08 марта 2012

Как вы указали, DivideByInt в основном существует для поддержки Seq.averageBy. Тот факт, что целочисленные типы не поддерживаются, имеет для меня смысл, поскольку среднее значение [1;2] должно быть 1.5, а не 1 (что даст вам реализация DivideByInt). Это вынуждает вас конвертировать ваши входные данные в числа с плавающей точкой, что дает вам ожидаемый ответ.

0 голосов
/ 19 августа 2014

Я явно опаздываю на вечеринку, но было бы интересно узнать, почему вы хотите создать функцию divBy2.Здесь есть две проблемы, и решение одной из них может быть достаточно, в зависимости от ваших потребностей.

Первая проблема заключается в том, что нет LanguagePrimitives.GenericTwo.Это легко исправить, но решение имеет ограниченное применение, если вы хотите определить конкретные функции деления для делителей, отличных от 2:

let inline divBy2 n =
    n / (LanguagePrimitives.GenericOne + LanguagePrimitives.GenericOne)

Для меньшего набора текста вы можете присвоить LanguagePrimitives.GenericOne переменной, котораястановится более полезным по мере увеличения величины вашего делителя:

let inline divBy4 n =
    let one = LanguagePrimitives.GenericOne
    let two = one + one
    n / (two + two)

Это решение также бесполезно, если вы хотите создать общую функцию.«Пользовательский» способ будет выглядеть следующим образом:

let inline divBy divisor dividend = dividend / divisor

Мы можем использовать это с частичным применением функции, чтобы наполовину сократить список байтов, например, так:

let halfBytes = [ 1uy .. 10uy ] |> List.map (divBy 2uy)

Но мы можем сделатьлучше.Эта проблема относится ко всем некоммутативным операторам, включая вычитание.Чтобы обойти это, мы можем определить

let flip f a b = f b a

Это позволяет, например,

let scaledInThousands = [ 0m .. 500m .. 3000m ] |> List.map (flip (/) 1000m)
let decrementedIntegers = [ 1 .. 10 ] |> List.map (flip (-) 1)

Если вы хотите, вы все равно можете определить функцию divBy:

let inline divBy n = flip (/) n
let halfInts = [ 1 .. 10 ] |> List.map (divBy 2)
let halfLongs = [ 1L .. 10L ] |> List.map (divBy 2L)
let fifthLongs = [ 1L .. 10L ] |> List.map (divBy 5L)
let oneThroughTenOverPi = [ 1.0 .. 10.0 ] |> List.map (divBy System.Math.PI)
0 голосов
/ 02 марта 2012

Можете ли вы определить это так?

let inline DivBy2 n = 
  let one = LanguagePrimitives.GenericOne
  n / (one + one)
...