Изучай Haskell во имя добра! (Липовача) - страница 22

Помните генератор списка, который мы использовали ранее: он фильтровал строку так, что оставались только прописные буквы? Вот как это выглядит с объявлением типа:

>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 – это действительное число с плавающей точкой одинарной точности. Добавьте в файл ещё одну функцию: