F # - Дженерики

Обобщения позволяют отложить спецификацию типа данных элементов программирования в классе или методе до тех пор, пока он не будет фактически использован в программе. Другими словами, универсальные шаблоны позволяют вам написать класс или метод, который может работать с любым типом данных.

Вы пишете спецификации для класса или метода с заменяющими параметрами для типов данных. Когда компилятор встречает конструктор для класса или вызов функции для метода, он генерирует код для обработки определенного типа данных.

В F # значения функций, методы, свойства и типы агрегатов, такие как классы, записи и размеченные объединения, могут быть универсальными.

Универсальные конструкции содержат по крайней мере один параметр типа. Универсальные функции и типы позволяют писать код, работающий с различными типами, без повторения кода для каждого типа.

Синтаксис

Синтаксис для написания общей конструкции следующий:

// Explicitly generic function.
let function-name<type-parameters> parameter-list =
   function-body

// Explicitly generic method.
[ static ] member object-identifer.method-name<type-parameters> parameter-list [ return-type ] =
   method-body

// Explicitly generic class, record, interface, structure,
// or discriminated union.
type type-name<type-parameters> type-definition

Примеры

(* Generic Function *)
let printFunc<'T> x y =
   printfn "%A, %A" x y

printFunc<float> 10.0 20.0

Когда вы компилируете и выполняете программу, она дает следующий результат:

10.0, 20.0

Вы также можете сделать функцию универсальной, используя синтаксис одинарных кавычек -

(* Generic Function *)
let printFunction (x: 'a) (y: 'a) =
   printfn "%A %A" x y

printFunction 10.0 20.0

Когда вы компилируете и выполняете программу, она дает следующий результат:

10.0 20.0

Обратите внимание, что при использовании общих функций или методов может не потребоваться указывать аргументы типа. Однако в случае двусмысленности вы можете указать аргументы типа в угловых скобках, как мы это сделали в первом примере.

Если у вас более одного типа, вы разделяете несколько аргументов типа запятыми.

Общий класс

Как и универсальные функции, вы также можете писать универсальные классы. Следующий пример демонстрирует это -

type genericClass<'a> (x: 'a) =
   do printfn "%A" x

let gr = new genericClass<string>("zara")
let gs = genericClass( seq { for i in 1 .. 10 -> (i, i*i) } )

Когда вы компилируете и выполняете программу, она дает следующий результат:

"zara"
seq [(1, 1); (2, 4); (3, 9); (4, 16); ...]