Ключевое слово type против newtype и data
К этому моменту, возможно, вы с трудом улавливаете различия между ключевыми словами >type
, >data
и >newtype
. Поэтому давайте немного повторим пройденное.
Ключевое слово >type
предназначено для создания синонимов типов. Мы просто даём другое имя уже существующему типу, чтобы на этот тип было проще сослаться. Скажем, мы написали следующее:
>type IntList = [Int]
Всё, что это нам даёт, – возможность сослаться на тип >[Int]
как >IntList
. Их можно использовать взаимозаменяемо. Мы не получаем конструктор данных >IntList
или что-либо в этом роде. Поскольку идентификаторы >[Int]
и >IntList
являются лишь двумя способами сослаться на один и тот же тип, неважно, какое имя мы используем в наших аннотациях типов:
>ghci> ([1,2,3] :: IntList) ++ ([1,2,3] :: [Int])
>[1,2,3,1,2,3]
Мы используем синонимы типов, когда хотим сделать наши сигнатуры типов более наглядными. Мы даём типам имена, которые говорят нам что-либо об их предназначении в контексте функций, где они используются. Например, когда мы использовали ассоциативный список типа >[(String,String)]
для представления телефонной книги в главе 7, то дали ему синоним типа >PhoneBook
, чтобы сигнатуры типов наших функций легко читались.
Ключевое слово >newtype
предназначено для оборачивания существующих типов в новые типы – в основном чтобы для них можно было проще определить экземпляры некоторых классов типов. Когда мы используем ключевое слово >newtype
для оборачивания существующего типа, получаемый нами тип отделён от исходного. Предположим, мы определяем следующий тип при помощи декларации >newtype
:
>newtype CharList = CharList { getCharList :: [Char] }
Нельзя использовать оператор >++
, чтобы соединить значение типа >CharList
и список типа >[Char]
. Нельзя даже использовать оператор >++
, чтобы соединить два значения типа >CharList
, потому что оператор >++
работает только со списками, а тип >CharList
не является списком, хотя можно сказать, что >CharList
содержит список. Мы можем, однако, преобразовать два значения типа >CharList
в списки, соединить их с помощью оператора >++
, а затем преобразовать получившееся обратно в >CharList
.
Когда в наших объявлениях типа >newtype