. Это означает только то, что мы можем ссылаться на тип, используя другое имя. Можно написать: >[(1,2),(3,5),(8,9)] :: AssocList Int Int
, в результате чего числа в списке будут трактоваться как целые – но мы также сможем работать с этим списком как с обычным списком пар целых чисел. Синонимы типов (и вообще типы) могут использоваться в языке Haskell только при объявлении типов. Часть языка, относящаяся к объявлению типов, – собственно объявление типов (то есть при определении данных и типов) или часть объявления после символа >::
(два двоеточия). Символ >::
используется при декларировании или аннотировании типов.
Иди налево, потом направо
Ещё один чудесный тип, принимающий два других в качестве параметров, – это тип >Either
. Он определён приблизительно так:
>data Either a b = Left a | Right b deriving (Eq, Ord, Read, Show)
У него два конструктора данных. Если используется конструктор >Left
, его содержимое имеет тип >a
; если >Right
– содержимое имеет тип >b
. Таким образом, мы можем использовать данный тип для инкапсуляции значения одного из двух типов. Когда мы работаем с типом >Either a b
, то обычно используем сопоставление с образцом по >Left
и >Right
и выполняем действия в зависимости от того, какой вариант совпал.
>ghci> Right 20
>Right 20
>ghci> Left "в00т"
>Left "в00т"
>ghci> :t Right 'a'
>Right 'a' :: Either a Char ghci> :t Left True
>Left True :: Either Bool b
Из приведённого примера следует, что типом значения >Left
>True
является >Either
>Bool
>b
. Первый параметр типа >Bool
, поскольку значение создано конструктором >Left
; второй же параметр остался полиморфным. Ситуация подобна тому как значение >Nothing
имеет тип >Maybe
>a
.
Мы видели, что тип >Maybe
главным образом используется для того, чтобы представить результат вычисления, которое может завершиться неудачей. Но иногда тип >Maybe
не так удобен, поскольку значение >Nothing
не несёт никакой информации, кроме того что что-то пошло не так. Это нормально для функций, которые могут выдавать ошибку только в одном случае – или если нам просто не интересно, как и почему функция «упала». Поиск в отображении типа >Data.Map
может завершиться неудачей, только если искомый ключ не найден, так что мы знаем, что случилось. Но если нам нужно знать, почему не сработала некоторая функция, обычно мы возвращаем результат типа >Either a b
, где >a
– это некоторый тип, который может нам что-нибудь рассказать о причине ошибки, и >b
– результат удачного вычисления. Следовательно, ошибки используют конструктор данных >Left
, правильные результаты используют конструктор >Right