F# проверенный объем арифметики

F# позволяет использовать проверенную арифметику путем открытия Checked модуль, который переопределяет стандартные операторы, чтобы быть проверенными операторами, например:

open Checked
let x = 1 + System.Int32.MaxValue // overflow

закончится исключение арифметического переполнения.

Но что, если я хочу использовать проверенную арифметику в некотором небольшом объеме, как C#, позволяет с ключевым словом checked:

int x = 1 + int.MaxValue;             // ok
int y = checked { 1 + int.MaxValue }; // overflow

Как я могу управлять объемом переопределения операторов путем открытия Checked модуль или делает это меньшим как возможное?

19
задан controlflow 16 February 2010 в 07:20
поделиться

2 ответа

Вы всегда можете определить отдельный оператор или использовать затенение, или использовать скобки для создания внутренней области для временного затенения:

let f() =
    // define a separate operator
    let (+.) x y = Checked.(+) x y
    try 
        let x = 1 +. System.Int32.MaxValue
        printfn "ran ok"
    with e ->
        printfn "exception"
    try 
        let x = 1 + System.Int32.MaxValue
        printfn "ran ok"
    with e ->
        printfn "exception"
    // shadow (+)
    let (+) x y = Checked.(+) x y
    try 
        let x = 1 + System.Int32.MaxValue
        printfn "ran ok"
    with e ->
        printfn "exception"
    // shadow it back again
    let (+) x y = Operators.(+) x y
    try 
        let x = 1 + System.Int32.MaxValue
        printfn "ran ok"
    with e ->
        printfn "exception"
    // use parens to create a scope
    (
        // shadow inside
        let (+) x y = Checked.(+) x y
        try 
            let x = 1 + System.Int32.MaxValue
            printfn "ran ok"
        with e ->
            printfn "exception"
    )            
    // shadowing scope expires
    try 
        let x = 1 + System.Int32.MaxValue
        printfn "ran ok"
    with e ->
        printfn "exception"


f()    
// output:
// exception
// ran ok
// exception
// ran ok
// exception
// ran ok

Наконец, см. Также - отмечено + параметр компилятора:

http://msdn.microsoft.com/en-us/library/dd233171 (VS.100) .aspx

19
ответ дан 30 November 2019 в 03:38
поделиться

Вот сложная (но, возможно, интересная) альтернатива. Если вы пишете что-то серьезное, вам, вероятно, следует использовать одно из предложений Брайана, но просто из любопытства мне было интересно, можно ли написать выражение вычисления F # для этого. Вы можете объявить тип, представляющий int , который следует использовать только с проверенными операциями:

type CheckedInt = Ch of int with
  static member (+) (Ch a, Ch b) = Checked.(+) a b
  static member (*) (Ch a, Ch b) = Checked.(*) a b
  static member (+) (Ch a, b) = Checked.(+) a b
  static member (*) (Ch a, b) = Checked.(*) a b

Затем вы можете определить построитель вычислительных выражений (это вообще не монада, потому что типы операций полностью нестандартны):

type CheckedBuilder() = 
  member x.Bind(v, f) = f (Ch v)      
  member x.Return(Ch v) = v
let checked = new CheckedBuilder()  

Когда вы вызываете 'bind', он автоматически преобразует заданное целочисленное значение в целое число, которое должно использоваться с операциями checked , поэтому остальная часть кода будет использовать checked Операторы + и * объявлены как члены. Вы получите что-то вроде этого:

checked { let! a = 10000 
          let! b = a * 10000 
          let! c = b * 21 
          let! d = c + 47483648 // !
          return d }

Это вызывает исключение, потому что оно выходит за пределы отмеченной строки. Если вы измените число, он вернет значение int (поскольку член Return разворачивает числовое значение из типа Checked ). Это немного сумасшедший прием :-), но я подумал, что это может быть интересно!

(Примечание отмечено - ключевое слово, зарезервированное для использования в будущем, поэтому вы можете выбрать другое имя)

17
ответ дан 30 November 2019 в 03:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: