Алекс Каскет

http://casquete.es/

Вывод типов — это одна из функций F#, которая становится любимой у новых программистов. На практике (и очень кратко) это заставляет нас писать меньше типовых аннотаций. Например, со следующим кодом:

пусть х = 42

пусть правда = правда

Компилятор делает вывод, что «x» — это целое число, а «true» — логическое значение. В этом случае алгоритм определения типа определяет тип по значениям, расположенным справа. Но на этом алгоритм не останавливается, он может вывести тип аргументов и возвращаемых значений функции из тела функции. В этом примере:

пусть Истина n =

если n › 42, то верно

иначе ложно

Аргумент «n» используется при сравнении с целым числом, и функция возвращает логические значения, поэтому компилятор может легко сделать вывод, что функция принимает целое число и возвращает логическое значение. Но теперь давайте посмотрим на другой фрагмент кода:

добавим p q = p + q

В этом случае компилятор делает вывод, что функция принимает и возвращает целое число. Что является причиной этого? По сути, компилятор F#, в отсутствие какой-либо другой информации, выводит целое число как тип арифметического выражения. Ключевым в приведенном выше предложении является «любая другая информация», потому что, если, например, у нас есть объявление функции, и мы используем его следующим образом:

добавим p q = p + q

пусть результат = добавить 2,0 40,0

Сигнатура функции «добавить» меняется на «float -> float», потому что на этот раз компилятор выводит тип из первого использования функции. Вопрос в этой ситуации может заключаться в следующем: как мне создать функцию, которая может работать с целыми числами, числами с плавающей запятой или длинными числами?
Мы можем использовать ключевое слово 'inline' для определения встроенной функции, в которой код встроен в сайт вызова во время компиляции.

пусть встроенная сумма x y = x + y

В этой ситуации тип аргументов функции «сумма» статически разрешается, и сигнатура функции становится такой:

val встроенная сумма:

x: ^a -> y: ^b -> ^c

когда ( ^a или ^b) : (статический член ( + ) : ^a * ^b -> ^c)

Мы видим, что перед типом параметров стоит знак вставки (^), указывающий тип, который заменяется фактическим типом во время компиляции, а не во время выполнения. Предложение «когда» указывает ограничения, указывающие на то, что параметр типа должен предоставлять определенные методы, которые можно вызывать из тела функции. В этом случае тип должен предоставлять оператор суммы.
Когда функция не зависит от типа параметра, алгоритм вывода склонен рассматривать параметр как универсальный. Это то, что называется автоматическим обобщением. Например:

давайте сравним p q =

если p ‹ q, то -1

elif p › q тогда 1

иначе 0

В этом случае сигнатура этой функции:

val compare : p:’a -> q:’a -> int, когда ‘a : сравнение

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

List.sortBy(fun x -> x.Length) ["три"; "два"; "один"]

Но если мы перепишем код так:

["три"; "два"; «один»] |› List.sortBy (fun x -> x.Length)

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

Вывод

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

Чтобы узнать больше о F#, ознакомьтесь с курсами:
https://fsharp.tv/courses/
включая БЕСПЛАТНЫЙ вводный курс, который поможет вам начать работу с функциональным программированием.