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

2

Типы и классы типов

Поверь в типы


Мы уже говорили о том, что Haskell является статически типизированным языком. Тип каждого выражения известен во время компиляции – это залог безопасного кода. Если вы напишете программу, которая попытается поделить булевский тип на число, то она даже не скомпилируется.

И хорошо, потому что уж лучше ловить такие ошибки на этапе компиляции, чем наблюдать, как ваша программа аварийно закрывается во время работы! Всему в языке Haskell назначен свой тип, так что компилятор может сделать довольно много выводов о программе перед её компиляцией.

В отличие от языков Java или Pascal, у Haskell есть механизм вывода типов. Если мы напишем число, то нет необходимости указывать, что это число. Язык Haskell может вывести это сам, так что нам не приходится явно обозначать типы функций и выражений.

Мы изучили некоторые основы языка, лишь вскользь упомянув о типах. Тем не менее понимание системы типов – очень важная часть обучения языку Haskell.

Тип – это нечто вроде ярлыка, который есть у каждого выражения. Он говорит нам, к какой категории относится данное выражение. Выражение >True – булево, >"привет" – это строка, и т. д.

Явное определение типов

А сейчас воспользуемся интерпретатором GHCi для определения типов нескольких выражений. Мы сделаем это с помощью команды >:t, которая, если за ней следует любое правильное выражение, выдаст нам тип последнего. Итак…

>ghci> :t 'a'

>'a' :: Char

>ghci> :t True

>True :: Bool

>ghci> :t "ПРИВЕТ!"

>"ПРИВЕТ!" :: [Char]

>ghci> :t (True, 'a')

>(True, 'a') :: (Bool, Char)

>ghci> :t 4 == 5

>4 == 5 :: Bool



Мы видим, что >:t печатает выражения, за которыми следуют >:: и их тип. Символы >:: означают: «имеет тип». У явно указанных типов первый символ всегда в верхнем регистре. Символ >'a', как вы заметили, имеет тип >Char. Несложно сообразить, что это сокращение от «character» – символ. Константа >True имеет тип >Bool. Выглядит логично… Идём дальше.

Исследуя тип >"ПРИВЕТ!", получим >[Char]. Квадратные скобки указывают на список – следовательно, перед нами «список символов». В отличие от списков, каждый кортеж любой длины имеет свой тип. Так выражение >(True, 'a') имеет тип >(Bool, Char), тогда как выражение >('a','b','c') будет иметь тип >(Char, Char, Char). Выражение >4==5 всегда вернёт >False, поэтому его тип – >Bool.

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