Помните генератор списка, который мы использовали ранее: он фильтровал строку так, что оставались только прописные буквы? Вот как это выглядит с объявлением типа:
>removeNonUppercase :: [Char] –> [Char]
>removeNonUppercase st = [ c | c <– st, c `elem` ['А'..'Я']]
Функция >removeNonUppercase
имеет тип >[Char] –> [Char]
. Эта запись означает, что функция принимает одну строку в качестве параметра и возвращает другую в качестве результата.
А как записать тип функции, которая принимает несколько параметров? Вот, например, простая функция, принимающая три целых числа и складывающая их:
>addThree :: Int –> Int –> Int –> Int
>addThree x y z = x + y + z
Параметры разделены символами –>, и здесь нет никакого различия между параметрами и типом возвращаемого значения. Возвращаемый тип – это последний элемент в объявлении, а параметры – первые три.
Позже мы увидим, почему они просто разделяются с помощью символов >–>
, вместо того чтобы тип возвращаемого значения как-то специально отделялся от типов параметров (например, >Int, Int, Int –> Int
или что-то в этом духе).
Если вы хотите объявить тип вашей функции, но не уверены, каким он должен быть, то всегда можно написать функцию без него, а затем проверить тип с помощью >:t
. Функции – тоже выражения, так что >:t
будет работать с ними без проблем.
Обычные типы в языке Haskell
А вот обзор некоторых часто используемых типов.
• Тип >Int
обозначает целое число. Число 7 может быть типа >Int
, но 7.2 – нет. Тип >Int
ограничен: у него есть минимальное и максимальное значения. Обычно на 32-битных машинах максимально возможное значение типа >Int
– это 2 147 483 647, а минимально возможное – соответственно, –2 147 483 648.
ПРИМЕЧАНИЕ. Мы используем компилятор GHC, в котором множество возможных значений типа Int определено размером машинного слова на используемом компьютере. Так что если у вас 64-битный процессор, вполне вероятно, что наименьшим значением типа Int будет –2>63, а наибольшим 2>63–1.
• Тип >Integer
обозначает… э-э-э… тоже целое число. Основная разница в том, что он не имеет ограничения, поэтому может представлять большие числа. Я имею в виду – очень большие. Между тем тип >Int
более эффективен. В качестве примера сохраните следующую функцию в файл:
>factorial :: Integer –> Integer
>factorial n = product [1..n]
Затем загрузите этот файл в GHCi с помощью команды >:l
и проверьте её:
>ghci> factorial 50
>30414093201713378043612608166064768844377641568960512000000000000
• Тип >Float
– это действительное число с плавающей точкой одинарной точности. Добавьте в файл ещё одну функцию: