Статически разрешаемые параметры типов

Статически разрешаемый параметр типа — это параметр типа, который заменяется фактическим типом во время компиляции, а не во время выполнения. Им предшествует символ каретки (^).

Синтаксис

ˆtype-parameter

Remarks

В F # существует два различных вида параметров типа. Первый тип является стандартным параметром универсального типа. Они обозначаются апострофом ('), как в 'T и 'U . они эквивалентны параметрам универсального типа в других платформа .NET Framework языках. Другой тип является статически разрешаемым и обозначается символом курсора, как в ^T и ^U .

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

В следующей таблице перечислены сходства и различия между двумя типами параметров типа.

Компонент Универсальный шаблон Статическое разрешение
Синтаксис 'T, 'U ^T, ^U
Время разрешения Во время выполнения Время компиляции
Ограничения элементов Не может использоваться с ограничениями элементов. Может использоваться с ограничениями элементов.
Создание кода Тип (или метод) со стандартными параметрами универсального типа приводит к созданию одного универсального типа или метода. Создается несколько экземпляров типов и методов, по одному для каждого требуемого типа.
Использование с типами Может использоваться для типов. Не может использоваться для типов.
Использование со встроенными функциями Нет. Встроенная функция не может быть параметризована со стандартным параметром универсального типа. Да. Статически разрешаемые параметры типа нельзя использовать в функциях и методах, которые не являются встроенными.

Многие функции основной библиотеки F #, в частности, операторы, имеют статически разрешаемые параметры типа. Эти функции и операторы являются встроенными и приводят к эффективному созданию кода для числовых вычислений.

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

let inline (+@) x y = x + x * y
// Call that uses int.
printfn "%d" (1 +@ 1)
// Call that uses float.
printfn "%f" (1.0 +@ 0.5)

Разрешенный тип (+@) основан на использовании обоих (+) (*) параметров и, которые вызывают вывод типа для определения ограничений членов в статически разрешаемых параметрах типа. Разрешенный тип, как показано в интерпретаторе F #, выглядит следующим образом.

^a -> ^c -> ^d
when (^a or ^b) : (static member ( + ) : ^a * ^b -> ^d) and
(^a or ^c) : (static member ( * ) : ^a * ^c -> ^b)

Выходные данные выглядят следующим образом.

2
1.500000

Начиная с F # 4,1 можно также указать конкретные имена типов в статически разрешаемых сигнатурах параметров типа. В предыдущих версиях языка имя типа может быть выделено компилятором, но фактически не может быть указано в сигнатуре. Начиная с F # 4,1 можно также указать конкретные имена типов в статически разрешаемых сигнатурах параметров типа. Ниже приведен пример:

let inline konst x _ = x

type CFunctor() =
    static member inline fmap (f: ^a -> ^b, a: ^a list) = List.map f a
    static member inline fmap (f: ^a -> ^b, a: ^a option) =
        match a with
        | None -> None
        | Some x -> Some (f x)

    // default implementation of replace
    static member inline replace< ^a, ^b, ^c, ^d, ^e when ^a :> CFunctor and (^a or ^d): (static member fmap: (^b -> ^c) * ^d -> ^e) > (a, f) =
        ((^a or ^d) : (static member fmap : (^b -> ^c) * ^d -> ^e) (konst a, f))

    // call overridden replace if present
    static member inline replace< ^a, ^b, ^c when ^b: (static member replace: ^a * ^b -> ^c)>(a: ^a, f: ^b) =
        (^b : (static member replace: ^a * ^b -> ^c) (a, f))

let inline replace_instance< ^a, ^b, ^c, ^d when (^a or ^c): (static member replace: ^b * ^c -> ^d)> (a: ^b, f: ^c) =
        ((^a or ^c): (static member replace: ^b * ^c -> ^d) (a, f))

// Note the concrete type 'CFunctor' specified in the signature
let inline replace (a: ^a) (f: ^b): ^a0 when (CFunctor or  ^b): (static member replace: ^a *  ^b ->  ^a0) =
    replace_instance<CFunctor, _, _, _> (a, f)

См. также