Конструктор данных может принимать несколько параметров-значений и возвращать новое значение. Например, конструктор >Car
принимает три значения и возвращает одно – экземпляр типа >Car
. Таким же образом конструкторы типа могут принимать типы-параметры и создавать новые типы. На первый взгляд это несколько абстрактно, но на самом деле не так уж сложно. Если вы знакомы с шаблонами в языке С++, то увидите некоторые параллели. Чтобы получить более ясное представление о том, как работают типы-параметры, давайте посмотрим, как реализованы типы, с которыми мы уже встречались.
>data Maybe a = Nothing | Just a
В данном примере идентификатор >a
– тип-параметр (переменная типа, типовая переменная). Так как в выражении присутствует тип-параметр, мы называем идентификатор >Maybe
конструктором типов. В зависимости от того, какой тип данных мы хотим сохранять в типе >Maybe
, когда он не >Nothing
, конструктор типа может производить такие типы, как >Maybe Int
, >Maybe Car
, >Maybe String
и т. д. Ни одно значение не может иметь тип «просто >Maybe
», потому что это не тип как таковой – это конструктор типов. Для того чтобы он стал настоящим типом, значения которого можно создать, мы должны указать все типы-параметры в конструкторе типа.
Итак, если мы передадим тип >Char
как параметр в тип >Maybe
, то получим тип >Maybe Char
. Для примера: значение >Just 'a'
имеет тип >Maybe Char
.
Обычно нам не приходится явно передавать параметры конструкторам типов, поскольку в языке Haskell есть вывод типов. Поэтому когда мы создаём значение >Just 'a'
, Haskell тут же определяет его тип – >Maybe Char
.
Если мы всё же хотим явно указать тип как параметр, это нужно делать в типовой части выражений, то есть после символа