Вот сложная (но, возможно, интересная) альтернатива. Если вы пишете что-то серьезное, то вам, вероятно, следует использовать одно из предложений Brians, но просто из любопытства мне было интересно, можно ли написать выражение вычисления 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 { let! a = 10000
let! b = a * 10000
let! c = b * 21
let! d = c + 47483648 // !
return d }
Это вызывает исключение, потому что оно переполняется в отмеченной строке. Если вы измените число, оно вернет значение int
(поскольку элемент Return
разворачивает числовое значение из типа Checked
). Это немного сумасшедшая техника :-) но я подумал, что это может быть интересно!
(Примечание checked
- ключевое слово, зарезервированное для будущего использования, поэтому вы можете выбрать другое имя)