Каждая функция в языке F# имеет определенный тип. Тип функции складывается из типов параметров и типа результата функции:
тип_параметра1 -> тип_параметра2 -> тип_параметраN -> тип_результата
Типы параметров разделяются оператором ->
, а в конце этой цепи укзывается тип результата.
Например, возьмем следующую функцию:
let hello() = printfn "Hello"
Здесь функция hello имеет один параметр типа unit
и возвращает значение типа unit
(потому что выражение printfn "Hello"
возвращает значение этого типа).
Поэтому типом этой функции будет
unit -> unit
И этот тип мы можем использовать как и любой другой тип, например, при типизации значений и параметров функций. Например:
let hello() = printfn "Hello" let func: (unit -> unit) = hello func() // Hello
Здесь значение func
представляет тип unit -> unit
, то есть по сути представляет функцию, которая принимает параметр типа unit и возвращает также значение типа unit.
Поэтому этому значению мы можем присвоить функцию hello
, которая имеет тот же тип. И далее через func
фактически вызвать функцию hello
Возьмем другой пример - функция принимает два параметра типа int
и возвращает значение типа int
:
let sum x y = x + y
Эта функция имеет тип
int ->int-> int
Первые два int в этой цепи представляют типы параметров, а последний - тип результата.
И аналогично мы можем определить значение этого типа и присвоить ему функцию этого типа:
let sum x y = x + y let operation: int ->int-> int = sum let result = operation 5 6 // 11 printfn $"result = {result}"
Если для параметров явно указаны типы данных и эти параметры идут подряд через запятую, то в определении типа функции они разделяются звездочкой *. Например:
let printUser (name:string, age: int) = printfn $"name: {name} age: {age}"
Здесь тип функции printUser
:
string*int->unit
Однако если типизированные параметры идут не через запятую, а по отдельности, то они также разделяются оператором ->
:
let printUser (name:string)(age: int) = printfn $"name: {name} age: {age}" let display: string->int->unit = printUser display "Tom" 37
Аналогично как в случае с переменными, которые представляют отдельные значения, мы можем изменять переменные, которые представляют функции:
let sum x y = x + y let subtract x y = x - y let mutable operation: int ->int-> int = sum let result1 = operation 10 6 // 16 printfn $"result1 = {result1}" // result1 = 16 operation <-subtract let result2 = operation 10 6 // 4 printfn $"result2 = {result2}" // result2 = 4
Здесь определена переменная, которая представляет функцию с двумя параметрами типа int и результатом типа int. Соответственно мы можем этой переменной присваивать динамически функции, которые соответствуют данному типу функции.