Оператор переопределения (.. ..)
Если переопределить оператор (.. ..)
, как в ответе @ kvb, он переопределит этот оператор любого типа.Поскольку вы, вероятно, хотите, чтобы оператор (.. ..)
работал для пользовательского типа данных, достаточно переопределить статические члены (+)
и One
.Например, вот пользовательский числовой тип для модульной арифметики, взятый из @ блога Томаса :
type IntegerZ5 =
| Z5 of int
member z.ToInt32() =
let (Z5 n) = z in n
override z.ToString() =
sprintf "%d (mod 5)" (z.ToInt32())
static member Create(n) =
let z5 = n % 5
Z5(max ((z5 + 5) % 5) z5)
static member (+) (Z5 a, Z5 b) = IntegerZ5.Create(a + b)
static member (-) (Z5 a, Z5 b) = IntegerZ5.Create(a - b)
static member (*) (Z5 a, Z5 b) = IntegerZ5.Create(a * b)
static member Zero = Z5 0
static member One = Z5 1
let inline z5 a = IntegerZ5.Create(a)
При построении диапазона, начинающегося с нижней границы, (+)
и One
используется для поиска следующего элемента.Конструкция заканчивается, когда следующий элемент равен или превышает верхнюю границу диапазона.Теперь вы можете использовать IntegerZ5
в любом выражении диапазона:
let s1 = seq{z5 37..z5 3};; // seq [Z5 2; Z5 3]
let s2 = seq{z5 10..z5 22..z5 4};; // seq [Z5 0; Z5 2; Z5 4]
Использование оператора (.. ..)
Другое использование выражения диапазона - в for
петли.Я считаю это полезным во многих случаях:
let sum =
let mutable s = 0L
for i in 1L..1000L do (* or 1L..1L..1000L with an explicit step *)
s <- s + i
s
, потому что он более гибкий, чем for...to..do
, который ограничен только int
и подразумевает диапазон с шагом 1
:
let sum =
let mutable s = 0L
for i = 1L to 1000L do (* doesn't work *)
s <- s + i
s